{"openapi":"3.1.0","info":{"title":"LangWatch API","version":"1.0.0","description":"LangWatch openapi spec"},"servers":[{"url":"https://app.langwatch.ai"}],"security":[{"project_api_key":[]}],"paths":{"/":{"get":{"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"handle":{"type":["string","null"]},"scope":{"type":"string","enum":["ORGANIZATION","PROJECT"]},"name":{"type":"string"},"updatedAt":{"type":"string"},"projectId":{"type":"string"},"organizationId":{"type":"string"},"version":{"type":"number"},"versionId":{"type":"string"},"versionCreatedAt":{"type":"string"},"model":{"type":"string"},"prompt":{"type":"string"},"messages":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string","enum":["user","assistant","system"]},"content":{"type":"string"}},"required":["role","content"]}},"response_format":{"type":["object","null"],"properties":{"type":{"type":"string","enum":["json_schema"]},"json_schema":{"type":"object","properties":{"name":{"type":"string"},"schema":{"type":"object"}},"required":["name","schema"]}},"required":["type","json_schema"]}},"required":["id","handle","scope","name","updatedAt","projectId","organizationId","version","versionId","versionCreatedAt","model","prompt","messages","response_format"]}}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}},"operationId":"getIndex","parameters":[],"description":"Get all prompts for a project"},"post":{"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"handle":{"type":["string","null"]},"scope":{"type":"string","enum":["ORGANIZATION","PROJECT"]},"name":{"type":"string"},"updatedAt":{"type":"string"},"projectId":{"type":"string"},"organizationId":{"type":"string"},"version":{"type":"number"},"versionId":{"type":"string"},"versionCreatedAt":{"type":"string"},"model":{"type":"string"},"prompt":{"type":"string"},"messages":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string","enum":["user","assistant","system"]},"content":{"type":"string"}},"required":["role","content"]}},"response_format":{"type":["object","null"],"properties":{"type":{"type":"string","enum":["json_schema"]},"json_schema":{"type":"object","properties":{"name":{"type":"string"},"schema":{"type":"object"}},"required":["name","schema"]}},"required":["type","json_schema"]}},"required":["id","handle","scope","name","updatedAt","projectId","organizationId","version","versionId","versionCreatedAt","model","prompt","messages","response_format"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}},"operationId":"postIndex","parameters":[],"description":"Create a new prompt with default initial version","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"handle":{"type":"string","pattern":"^[a-z0-9_-]+(?:\\/[a-z0-9_-]+)?$"},"scope":{"type":"string","enum":["ORGANIZATION","PROJECT"],"default":"PROJECT"},"authorId":{"type":"string"},"prompt":{"type":"string"},"messages":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string","enum":["user","assistant","system"]},"content":{"type":"string"}},"required":["role","content"]}},"inputs":{"type":"array","items":{"type":"object","properties":{"identifier":{"type":"string","minLength":1},"type":{"type":"string","enum":["str","float","bool","image","list[str]","list[float]","list[int]","list[bool]","dict"]}},"required":["identifier","type"]}},"outputs":{"type":"array","items":{"type":"object","properties":{"identifier":{"type":"string","minLength":1},"type":{"type":"string","enum":["str","float","bool","json_schema"]},"json_schema":{"type":"object","properties":{"type":{"type":"string","minLength":1}},"required":["type"],"additionalProperties":true}},"required":["identifier","type"]}}},"required":["handle"]}}}}}},"/api/annotations":{"get":{"description":"Returns all annotations for project","parameters":[{"name":"anchor","in":"query","description":"Which comments to return. Omitted returns every comment, including the ones left on a span, a field, an attribute or a message; \"trace\" returns only the comments about whole traces.","required":false,"schema":{"type":"string","enum":["trace","all"]}}],"responses":{"200":{"description":"Annotation response","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Annotation"}}}}}}},"400":{"description":"Unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/annotations/trace/{id}":{"get":{"description":"Returns all annotations for single trace","parameters":[{"name":"id","in":"path","description":"ID of trace to fetch","required":true,"schema":{"type":"string"}},{"name":"anchor","in":"query","description":"Which comments to return. Omitted returns every comment, including the ones left on a span, a field, an attribute or a message; \"trace\" returns only the comments about whole traces.","required":false,"schema":{"type":"string","enum":["trace","all"]}}],"responses":{"200":{"description":"Annotation response","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Annotation"}}}}}}},"400":{"description":"Unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"description":"Create an annotation for a single trace","parameters":[{"name":"id","in":"path","description":"ID of the trace to annotate","required":true,"schema":{"type":"string"}}],"requestBody":{"description":"Annotation data","required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"comment":{"type":"string"},"isThumbsUp":{"type":"boolean"},"email":{"type":"string"}},"required":["comment","isThumbsUp"]}}}},"responses":{"200":{"description":"Annotation created","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/Annotation"}}}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/annotations/{id}":{"get":{"description":"Returns a single annotation based on the ID supplied","parameters":[{"name":"id","in":"path","description":"ID of annotation to fetch","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Annotation response","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/Annotation"}}}}}},"400":{"description":"Unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"description":"Deletes a single annotation based on the ID supplied","parameters":[{"name":"id","in":"path","description":"ID of annotation to delete","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Annotation response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"message":{"type":"string"}}}}}},"400":{"description":"Unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No annotation with that ID exists in the project","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["annotation_not_found"]},"message":{"type":"string"}},"required":["error","message"]}}}}}},"patch":{"description":"Updates a single annotation based on the ID supplied","parameters":[{"name":"id","in":"path","description":"ID of annotation to delete","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"comment":{"type":"string"},"isThumbsUp":{"type":"boolean"},"email":{"type":"string"}},"required":["comment","isThumbsUp"]}}}},"responses":{"200":{"description":"Annotation response","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/Annotation"}}}}}},"400":{"description":"Unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/trace/search":{"post":{"summary":"Search traces","description":"Search for traces based on given criteria","tags":["Traces"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchRequest"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponse"}}}}}}},"/api/trace/{id}":{"get":{"description":"Returns single trace details based on the ID supplied","parameters":[{"name":"id","in":"path","description":"ID of trace to share","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Trace details with spans and evaluations","content":{"application/json":{"schema":{"type":"object","properties":{"trace_id":{"type":"string","example":"trace_BKZL_X0TKSD4oa1aBJTc_"},"project_id":{"type":"string","example":"KAXYxPR8MUgTcP8CF193y"},"metadata":{"type":"object","properties":{"sdk_version":{"type":"string","example":"0.1.11"},"sdk_language":{"type":"string","example":"python"}}},"timestamps":{"type":"object","properties":{"started_at":{"type":"integer","example":1721382486868},"inserted_at":{"type":"integer","example":1721382492894},"updated_at":{"type":"integer","example":1721382492894}}},"input":{"type":"object","properties":{"value":{"type":"string","example":"hi"}}},"output":{"type":"object","properties":{"value":{"type":"string","example":"Hey there! 👋😊"}}},"metrics":{"type":"object","properties":{"first_token_ms":{"type":"integer","example":1449},"total_time_ms":{"type":"integer","example":1543},"prompt_tokens":{"type":"integer","example":20},"completion_tokens":{"type":"integer","example":7},"tokens_estimated":{"type":"boolean","example":true}}},"error":{"type":"object","nullable":true,"properties":{"stacktrace":{"type":"array","items":{"type":"string"}},"message":{"type":"string"},"has_error":{"type":"boolean"}},"example":null},"indexing_md5s":{"type":"array","items":{"type":"string"},"example":["cccd21e0b70c706034dfd9f7772816a3"]},"spans":{"type":"array","items":{"type":"object","properties":{"trace_id":{"type":"string","example":"trace_BKZL_X0TKSD4oa1aBJTc_"},"span_id":{"type":"string","example":"span_h1xUkcUJilhudDrLeQbR_"},"timestamps":{"type":"object","properties":{"finished_at":{"type":"integer","example":1721382488392},"updated_at":{"type":"integer","example":1721382492027},"started_at":{"type":"integer","example":1721382486895},"first_token_at":{"type":"integer","example":1721382488317},"inserted_at":{"type":"integer","example":1721382492027}}},"type":{"type":"string","example":"llm"},"error":{"type":"object","nullable":true,"properties":{"stacktrace":{"type":"array","items":{"type":"string"}},"message":{"type":"string"},"has_error":{"type":"boolean"}},"example":null},"params":{"type":"object","properties":{"stream":{"type":"boolean","example":true},"temperature":{"type":"number","example":1}}},"project_id":{"type":"string","example":"KAXYxPR8MUgTcP8CF193y"},"parent_id":{"type":"string","nullable":true,"example":"span_ijZNjUMTz3ys0Z0YKwF_T"},"name":{"type":"string","nullable":true,"example":null},"model":{"type":"string","example":"openai/gpt-4o"},"metrics":{"type":"object","properties":{"tokens_estimated":{"type":"boolean","example":true},"completion_tokens":{"type":"integer","example":7},"prompt_tokens":{"type":"integer","example":20}}},"input":{"type":"object","properties":{"type":{"type":"string","example":"chat_messages"},"value":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string","example":"system"},"content":{"type":"string","example":"You are a helpful assistant that only reply in short tweet-like responses, using lots of emojis."}}},"example":[{"role":"system","content":"You are a helpful assistant that only reply in short tweet-like responses, using lots of emojis."},{"role":"user","content":"hi"}]}}},"output":{"type":"object","properties":{"type":{"type":"string","example":"chat_messages"},"value":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string","example":"assistant"},"content":{"type":"string","example":"Hey there! 👋😊"}}},"example":[{"role":"assistant","content":"Hey there! 👋😊"}]}}}}}},"evaluations":{"type":"array","items":{"type":"object","properties":{"evaluation_id":{"type":"string","example":"check_VCagriZHNWICSOM09dXjM"},"name":{"type":"string","example":"Ragas Answer Relevancy"},"type":{"type":"string","example":"ragas/response_relevancy"},"trace_id":{"type":"string","example":"trace_BKZL_X0TKSD4oa1aBJTc_"},"project_id":{"type":"string","example":"KAXYxPR8MUgTcP8CF193y"},"status":{"type":"string","example":"error"},"timestamps":{"type":"object","properties":{"updated_at":{"type":"integer","example":1721383657788},"inserted_at":{"type":"integer","example":1721382493358}}},"error":{"type":"object","properties":{"stacktrace":{"type":"array","items":{"type":"string"},"example":["TypeError: fetch failed"]},"message":{"type":"string","example":"fetch failed"},"has_error":{"type":"boolean","example":true}}}}}}}}}}},"400":{"description":"Unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/trace/{id}/share":{"post":{"description":"Returns a public path for a trace","parameters":[{"name":"id","in":"path","description":"ID of trace to share","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Public path created","content":{"application/json":{"schema":{"type":"object","properties":{"path":{"type":"string"}}}}}},"400":{"description":"Unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/trace/{id}/unshare":{"post":{"description":"Deletes a public path for a trace","parameters":[{"name":"id","in":"path","description":"ID of trace to unshare","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Public path deleted","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}}},"400":{"description":"Unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/agent-cache/{name}":{"get":{"operationId":"getApiAgentCacheByName","description":"Read a cache entry by name. An entry that was never stored, or whose lifetime has passed, answers 404. Requires the agentCache:manage grain, because a caller that can overwrite an entry can already choose what the next read answers. A legacy project API key reaches this route, the same as it reaches the rest of the project surface.","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"value":{"type":"string"}},"required":["name","value"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"404":{"description":"The project holds no live entry under that name","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"parameters":[{"in":"path","name":"name","schema":{"type":"string","pattern":"^[A-Z][A-Z0-9_]*$","minLength":1,"maxLength":64},"required":true}],"security":[{"project_api_key":[]}]},"put":{"operationId":"putApiAgentCacheByName","description":"Store a value under a name, whether or not the name is held yet. The value is encrypted at rest and expires by itself after ttl_seconds, which defaults to 900 seconds. The last write wins.","responses":{"200":{"description":"Entry stored","content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"ttl_seconds":{"type":"number"}},"required":["name","ttl_seconds"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"parameters":[{"in":"path","name":"name","schema":{"type":"string","pattern":"^[A-Z][A-Z0-9_]*$","minLength":1,"maxLength":64},"required":true}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"value":{"type":"string","minLength":1},"ttl_seconds":{"type":"integer","minimum":5,"maximum":86400}},"required":["value"]}}}},"security":[{"project_api_key":[]}]},"delete":{"operationId":"deleteApiAgentCacheByName","description":"Remove a cache entry. A name the project does not hold answers the same as one it does, so a caller can clear an entry without reading it first.","responses":{"200":{"description":"Entry removed","content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"deleted":{"type":"boolean"}},"required":["name","deleted"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"parameters":[{"in":"path","name":"name","schema":{"type":"string","pattern":"^[A-Z][A-Z0-9_]*$","minLength":1,"maxLength":64},"required":true}],"security":[{"project_api_key":[]}]}},"/api/agent-cache/{name}/claim":{"post":{"operationId":"postApiAgentCacheByNameClaim","description":"Store a value under a name only if the project does not hold that name yet. The answer says whether this caller is the one that took it: `claimed` is true when the value was written, and false when the name was already held, which leaves the held value alone. Losing is an ordinary answer and not a refusal, so a caller branches on `claimed` rather than on an error. This is what one row of a run uses to do work the rows beside it then reuse, instead of every row doing it at once. The value is encrypted at rest and expires by itself after ttl_seconds, which defaults to 900 seconds.","responses":{"200":{"description":"Claim resolved, taken or not","content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"claimed":{"type":"boolean"},"ttl_seconds":{"type":"number"}},"required":["name","claimed","ttl_seconds"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"parameters":[{"in":"path","name":"name","schema":{"type":"string","pattern":"^[A-Z][A-Z0-9_]*$","minLength":1,"maxLength":64},"required":true}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"value":{"type":"string","minLength":1},"ttl_seconds":{"type":"integer","minimum":5,"maximum":86400}},"required":["value"]}}}},"security":[{"project_api_key":[]}]}},"/api/v1/agents/connect/register":{"post":{"operationId":"registerConnectedAgentInstance","responses":{"200":{"description":"The instance is registered","content":{"application/json":{"schema":{"type":"object","properties":{"frame":{"anyOf":[{"type":"object","properties":{"protocol":{"type":"number","const":1},"type":{"type":"string","const":"registered"},"agents":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"environment":{"type":"string"},"id":{"type":"string"},"url":{"type":"string"},"parameterNotes":{"type":"array","items":{"type":"string"}},"scope":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"shared"}},"required":["kind"]},{"type":"object","properties":{"kind":{"type":"string","const":"owner"}},"required":["kind"]},{"type":"object","properties":{"kind":{"type":"string","const":"host"},"hostLabel":{"type":"string"}},"required":["kind","hostLabel"]}]}},"required":["name","environment","id","url","parameterNotes","scope"]}},"heartbeatIntervalMs":{"type":"integer","exclusiveMinimum":0},"instanceId":{"type":"string"}},"required":["protocol","type","agents","heartbeatIntervalMs","instanceId"]},{"type":"object","properties":{"protocol":{"type":"number","const":1},"type":{"type":"string","const":"refused"},"code":{"type":"string","enum":["api_key_invalid","project_required","permission_denied","key_type_not_allowed","replica_count_unsupported","parameters_invalid","environment_invalid","protocol_invalid"]},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}}},"required":["protocol","type","code","message"]}],"description":"The registered frame, or the refused frame with its reason."},"instanceToken":{"type":"string","description":"The token the poll and frames endpoints are addressed with, in the X-Agent-Instance-Token header. Present when the register was accepted."}},"required":["frame"]}}}},"401":{"description":"The API key is not valid: a refused frame"},"403":{"description":"The key type or its permissions cannot connect an agent: a refused frame"},"422":{"description":"The body is not a register frame, or an agent of it is not valid: a refused frame"},"503":{"description":"The deployment runs several replicas without Redis: a refused frame"}},"description":"Register the connected agents of a process over HTTP, for a network that blocks WebSockets. The body is the register frame of the connect protocol. Answers with the registered frame and the instance token the poll and frames endpoints are addressed with, or with a refused frame.","tags":["Agents"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"protocol":{"type":"number","enum":[1]},"type":{"type":"string","enum":["register"]},"sdk":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":64},"version":{"type":"string","minLength":1,"maxLength":64},"language":{"type":"string","minLength":1,"maxLength":32}},"required":["name","version","language"],"additionalProperties":false},"instance":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128},"hostname":{"type":"string","maxLength":255},"username":{"type":"string","maxLength":255},"pid":{"type":"integer","minimum":0},"startedAt":{"type":"string","maxLength":64},"label":{"type":"string","maxLength":128},"inFlightCallIds":{"type":"array","items":{"type":"string","maxLength":128},"maxItems":1000,"default":[]},"maxConcurrency":{"type":"integer","exclusiveMinimum":0,"maximum":1000}},"required":["id","hostname","username","pid","startedAt"],"additionalProperties":false},"agents":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"environment":{"type":"string","minLength":1,"maxLength":64},"parameters":{"type":"object","additionalProperties":{},"default":{}},"concurrency":{"type":"integer","exclusiveMinimum":0,"maximum":1000},"timeoutMs":{"type":"integer","exclusiveMinimum":0},"sticky":{"type":"boolean"}},"required":["name","environment"],"additionalProperties":false},"minItems":1,"maxItems":100}},"required":["protocol","type","sdk","instance","agents"],"additionalProperties":false}}}},"security":[{"project_api_key":[]}]}},"/api/v1/agents/connect/poll":{"get":{"operationId":"pollConnectedAgentInstance","responses":{"200":{"description":"The frames waiting for the instance, possibly none","content":{"application/json":{"schema":{"type":"object","properties":{"frames":{"type":"array","items":{"anyOf":[{"type":"object","properties":{"protocol":{"type":"number","const":1},"type":{"type":"string","const":"call"},"callId":{"type":"string"},"agentId":{"type":"string"},"threadId":{"type":"string"},"messages":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string","minLength":1}},"required":["role"],"additionalProperties":true}},"newMessages":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string","minLength":1}},"required":["role"],"additionalProperties":true}},"params":{"type":"object","propertyNames":{"type":"string","pattern":"^[A-Za-z_][A-Za-z0-9_]*$"},"additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"}]}},"session":{},"traceparent":{"type":["string","null"]},"deadlineAt":{"type":"integer"},"run":{"type":"object","properties":{"scenarioRunId":{"type":"string"},"scenarioName":{"type":"string"},"batchRunId":{"type":"string"}}}},"required":["protocol","type","callId","agentId","threadId","messages","newMessages","params","traceparent","deadlineAt","run"]},{"type":"object","properties":{"protocol":{"type":"number","const":1},"type":{"type":"string","const":"cancel"},"callId":{"type":"string","minLength":1}},"required":["protocol","type","callId"]}]},"description":"The call and cancel frames waiting for the instance; empty once the poll wait passes with none."}},"required":["frames"]}}}},"401":{"description":"The API key is not valid: a refused frame"},"410":{"description":"The instance token is not known; register the instance again"}},"description":"Wait for the next call and cancel frames of a registered instance, up to 25 seconds, then answer with what is waiting or with an empty list. Each poll refreshes the instance presence, so a process that polls reads Online. Addressed with the instance token in the X-Agent-Instance-Token header.","tags":["Agents"],"security":[{"project_api_key":[]}]}},"/api/v1/agents/connect/frames":{"post":{"operationId":"postConnectedAgentFrames","responses":{"200":{"description":"The frames were taken","content":{"application/json":{"schema":{"type":"object","properties":{"accepted":{"type":"integer","description":"How many frames were taken."}},"required":["accepted"]}}}},"401":{"description":"The API key is not valid: a refused frame"},"410":{"description":"The instance token is not known; register the instance again"},"422":{"description":"A frame is not one the endpoint takes"}},"description":"Post the ack, result and deregister frames of a registered instance. Addressed with the instance token in the X-Agent-Instance-Token header.","tags":["Agents"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"frames":{"type":"array","items":{"anyOf":[{"type":"object","properties":{"protocol":{"type":"number","enum":[1]},"type":{"type":"string","enum":["ack"]},"callId":{"type":"string","minLength":1}},"required":["protocol","type","callId"],"additionalProperties":false},{"type":"object","properties":{"protocol":{"type":"number","enum":[1]},"type":{"type":"string","enum":["result"]},"callId":{"type":"string","minLength":1},"output":{"anyOf":[{"type":"string"},{"type":"object","properties":{"role":{"type":"string","minLength":1}},"required":["role"],"additionalProperties":true},{"type":"array","items":{"type":"object","properties":{"role":{"type":"string","minLength":1}},"required":["role"],"additionalProperties":true}}]},"session":{},"error":{"type":"object","properties":{"code":{"type":"string","minLength":1,"maxLength":64},"message":{"type":"string","maxLength":4000}},"required":["code","message"],"additionalProperties":false}},"required":["protocol","type","callId"],"additionalProperties":false},{"type":"object","properties":{"protocol":{"type":"number","enum":[1]},"type":{"type":"string","enum":["deregister"]}},"required":["protocol","type"],"additionalProperties":false}]},"minItems":1,"maxItems":100,"description":"Ack, result and deregister frames, in order."}},"required":["frames"],"additionalProperties":false}}}},"security":[{"project_api_key":[]}]}},"/api/v1/agents":{"get":{"operationId":"listAgents","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"type":"string","enum":["signature","code","workflow","http","connected","voice"],"description":"The kind of agent. A connected agent is registered from code by the SDK and cannot be created or reconfigured through this API."},"config":{"type":["object","null"],"additionalProperties":{}},"environment":{"type":["string","null"],"description":"The environment a connected agent registered with, for example production or development. Null for every other kind."},"ownerUserId":{"type":["string","null"],"description":"The user a personal development agent belongs to. Only that user can run simulations against it. Null when the agent is shared."},"hostLabel":{"type":["string","null"],"description":"The machine a development agent registered from with a project or service key. Null when the agent is personal or shared."},"lastSeenAt":{"type":["string","null"],"description":"When an instance of a connected agent was last connected. Null for every other kind."},"parameters":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","pattern":"^[A-Za-z_][A-Za-z0-9_]*$","minLength":1,"maxLength":64},"description":{"type":"string","maxLength":500},"defaultValue":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"secret":{"type":"boolean"},"type":{"type":"string","enum":["string","number","boolean"]},"options":{"type":"array","items":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"maxItems":50},"required":{"type":"boolean"}},"required":["name"]},"description":"The run parameters a connected agent declares from its function signature: name, type, options, default and description. Empty for every other kind."},"owner":{"type":["object","null"],"properties":{"userId":{"type":"string"},"name":{"type":["string","null"]}},"required":["userId","name"],"description":"The person a personal development agent belongs to. Null when the agent is shared or host-scoped."},"status":{"type":"string","enum":["online","offline"],"description":"online while at least one process running the connected agent is connected; offline otherwise, and always for every other kind."},"instances":{"type":"array","items":{"type":"object","properties":{"instanceId":{"type":"string"},"hostname":{"type":"string"},"username":{"type":"string"},"pid":{"type":"number"},"label":{"type":["string","null"]},"sdk":{"type":"object","properties":{"name":{"type":"string"},"version":{"type":"string"},"language":{"type":"string"}},"required":["name","version","language"]},"connectedAt":{"type":"string"},"inflight":{"type":"number"},"maxConcurrency":{"type":"number"}},"required":["instanceId","hostname","username","pid","label","sdk","connectedAt","inflight","maxConcurrency"]},"description":"The processes currently connected for a connected agent: hostname, user, pid, SDK and how many calls each has in flight. Empty for every other kind."},"selectable":{"type":"boolean","description":"Whether the credential making this request can run simulations against the agent. False for a personal development agent that belongs to somebody else, which is listed all the same so it can be told apart from the other agents of the same name."},"notSelectableReason":{"type":["string","null"],"enum":["owned_by_another_person",null],"description":"Why the agent cannot be run by this credential. Null when it can."},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"platformUrl":{"type":"string","format":"uri"}},"required":["id","name","type","config","environment","ownerUserId","hostLabel","lastSeenAt","parameters","owner","status","instances","selectable","notSelectableReason","createdAt","updatedAt","platformUrl"]}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}},"required":["page","limit","total","totalPages"]}},"required":["data","pagination"]}}}}},"description":"List the project's agents, paginated, with the presence and owner of each connected agent. Archived agents are left out.","tags":["Agents"],"parameters":[{"in":"query","name":"page","schema":{"type":"integer","exclusiveMinimum":0,"default":1}},{"in":"query","name":"limit","schema":{"type":"integer","exclusiveMinimum":0,"maximum":1000,"default":50}}],"security":[{"project_api_key":[]}]},"post":{"operationId":"createAgent","responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"type":"string","enum":["signature","code","workflow","http","connected","voice"],"description":"The kind of agent. A connected agent is registered from code by the SDK and cannot be created or reconfigured through this API."},"config":{"type":["object","null"],"additionalProperties":{}},"environment":{"type":["string","null"],"description":"The environment a connected agent registered with, for example production or development. Null for every other kind."},"ownerUserId":{"type":["string","null"],"description":"The user a personal development agent belongs to. Only that user can run simulations against it. Null when the agent is shared."},"hostLabel":{"type":["string","null"],"description":"The machine a development agent registered from with a project or service key. Null when the agent is personal or shared."},"lastSeenAt":{"type":["string","null"],"description":"When an instance of a connected agent was last connected. Null for every other kind."},"parameters":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","pattern":"^[A-Za-z_][A-Za-z0-9_]*$","minLength":1,"maxLength":64},"description":{"type":"string","maxLength":500},"defaultValue":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"secret":{"type":"boolean"},"type":{"type":"string","enum":["string","number","boolean"]},"options":{"type":"array","items":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"maxItems":50},"required":{"type":"boolean"}},"required":["name"]},"description":"The run parameters a connected agent declares from its function signature: name, type, options, default and description. Empty for every other kind."},"owner":{"type":["object","null"],"properties":{"userId":{"type":"string"},"name":{"type":["string","null"]}},"required":["userId","name"],"description":"The person a personal development agent belongs to. Null when the agent is shared or host-scoped."},"status":{"type":"string","enum":["online","offline"],"description":"online while at least one process running the connected agent is connected; offline otherwise, and always for every other kind."},"instances":{"type":"array","items":{"type":"object","properties":{"instanceId":{"type":"string"},"hostname":{"type":"string"},"username":{"type":"string"},"pid":{"type":"number"},"label":{"type":["string","null"]},"sdk":{"type":"object","properties":{"name":{"type":"string"},"version":{"type":"string"},"language":{"type":"string"}},"required":["name","version","language"]},"connectedAt":{"type":"string"},"inflight":{"type":"number"},"maxConcurrency":{"type":"number"}},"required":["instanceId","hostname","username","pid","label","sdk","connectedAt","inflight","maxConcurrency"]},"description":"The processes currently connected for a connected agent: hostname, user, pid, SDK and how many calls each has in flight. Empty for every other kind."},"selectable":{"type":"boolean","description":"Whether the credential making this request can run simulations against the agent. False for a personal development agent that belongs to somebody else, which is listed all the same so it can be told apart from the other agents of the same name."},"notSelectableReason":{"type":["string","null"],"enum":["owned_by_another_person",null],"description":"Why the agent cannot be run by this credential. Null when it can."},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"platformUrl":{"type":"string","format":"uri"}},"required":["id","name","type","config","environment","ownerUserId","hostLabel","lastSeenAt","parameters","owner","status","instances","selectable","notSelectableReason","createdAt","updatedAt","platformUrl"]}}}}},"description":"Create an agent from a name, a type and the configuration of that type. A connected agent is registered from code by the SDK and answers 422 agent_register_only here.","tags":["Agents"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"type":{"type":"string","enum":["signature","code","workflow","http","connected","voice"],"description":"The kind of agent to write. A connected agent is registered from code by the SDK, so \"connected\" is refused with agent_register_only."},"config":{"type":"object","additionalProperties":{}},"workflowId":{"type":"string"}},"required":["name","type","config"]}}}},"security":[{"project_api_key":[]}]}},"/api/v1/agents/{id}":{"get":{"operationId":"getAgent","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"type":"string","enum":["signature","code","workflow","http","connected","voice"],"description":"The kind of agent. A connected agent is registered from code by the SDK and cannot be created or reconfigured through this API."},"config":{"type":["object","null"],"additionalProperties":{}},"environment":{"type":["string","null"],"description":"The environment a connected agent registered with, for example production or development. Null for every other kind."},"ownerUserId":{"type":["string","null"],"description":"The user a personal development agent belongs to. Only that user can run simulations against it. Null when the agent is shared."},"hostLabel":{"type":["string","null"],"description":"The machine a development agent registered from with a project or service key. Null when the agent is personal or shared."},"lastSeenAt":{"type":["string","null"],"description":"When an instance of a connected agent was last connected. Null for every other kind."},"parameters":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","pattern":"^[A-Za-z_][A-Za-z0-9_]*$","minLength":1,"maxLength":64},"description":{"type":"string","maxLength":500},"defaultValue":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"secret":{"type":"boolean"},"type":{"type":"string","enum":["string","number","boolean"]},"options":{"type":"array","items":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"maxItems":50},"required":{"type":"boolean"}},"required":["name"]},"description":"The run parameters a connected agent declares from its function signature: name, type, options, default and description. Empty for every other kind."},"owner":{"type":["object","null"],"properties":{"userId":{"type":"string"},"name":{"type":["string","null"]}},"required":["userId","name"],"description":"The person a personal development agent belongs to. Null when the agent is shared or host-scoped."},"status":{"type":"string","enum":["online","offline"],"description":"online while at least one process running the connected agent is connected; offline otherwise, and always for every other kind."},"instances":{"type":"array","items":{"type":"object","properties":{"instanceId":{"type":"string"},"hostname":{"type":"string"},"username":{"type":"string"},"pid":{"type":"number"},"label":{"type":["string","null"]},"sdk":{"type":"object","properties":{"name":{"type":"string"},"version":{"type":"string"},"language":{"type":"string"}},"required":["name","version","language"]},"connectedAt":{"type":"string"},"inflight":{"type":"number"},"maxConcurrency":{"type":"number"}},"required":["instanceId","hostname","username","pid","label","sdk","connectedAt","inflight","maxConcurrency"]},"description":"The processes currently connected for a connected agent: hostname, user, pid, SDK and how many calls each has in flight. Empty for every other kind."},"selectable":{"type":"boolean","description":"Whether the credential making this request can run simulations against the agent. False for a personal development agent that belongs to somebody else, which is listed all the same so it can be told apart from the other agents of the same name."},"notSelectableReason":{"type":["string","null"],"enum":["owned_by_another_person",null],"description":"Why the agent cannot be run by this credential. Null when it can."},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"platformUrl":{"type":"string","format":"uri"}},"required":["id","name","type","config","environment","ownerUserId","hostLabel","lastSeenAt","parameters","owner","status","instances","selectable","notSelectableReason","createdAt","updatedAt","platformUrl"]}}}}},"description":"Read one agent with its presence, its owner and the run parameters it declares. An id the project does not hold answers 404 agent_not_found.","tags":["Agents"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1},"required":true,"description":"The agent id."}],"security":[{"project_api_key":[]}]},"patch":{"operationId":"updateAgent","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"type":"string","enum":["signature","code","workflow","http","connected","voice"],"description":"The kind of agent. A connected agent is registered from code by the SDK and cannot be created or reconfigured through this API."},"config":{"type":["object","null"],"additionalProperties":{}},"environment":{"type":["string","null"],"description":"The environment a connected agent registered with, for example production or development. Null for every other kind."},"ownerUserId":{"type":["string","null"],"description":"The user a personal development agent belongs to. Only that user can run simulations against it. Null when the agent is shared."},"hostLabel":{"type":["string","null"],"description":"The machine a development agent registered from with a project or service key. Null when the agent is personal or shared."},"lastSeenAt":{"type":["string","null"],"description":"When an instance of a connected agent was last connected. Null for every other kind."},"parameters":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","pattern":"^[A-Za-z_][A-Za-z0-9_]*$","minLength":1,"maxLength":64},"description":{"type":"string","maxLength":500},"defaultValue":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"secret":{"type":"boolean"},"type":{"type":"string","enum":["string","number","boolean"]},"options":{"type":"array","items":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"maxItems":50},"required":{"type":"boolean"}},"required":["name"]},"description":"The run parameters a connected agent declares from its function signature: name, type, options, default and description. Empty for every other kind."},"owner":{"type":["object","null"],"properties":{"userId":{"type":"string"},"name":{"type":["string","null"]}},"required":["userId","name"],"description":"The person a personal development agent belongs to. Null when the agent is shared or host-scoped."},"status":{"type":"string","enum":["online","offline"],"description":"online while at least one process running the connected agent is connected; offline otherwise, and always for every other kind."},"instances":{"type":"array","items":{"type":"object","properties":{"instanceId":{"type":"string"},"hostname":{"type":"string"},"username":{"type":"string"},"pid":{"type":"number"},"label":{"type":["string","null"]},"sdk":{"type":"object","properties":{"name":{"type":"string"},"version":{"type":"string"},"language":{"type":"string"}},"required":["name","version","language"]},"connectedAt":{"type":"string"},"inflight":{"type":"number"},"maxConcurrency":{"type":"number"}},"required":["instanceId","hostname","username","pid","label","sdk","connectedAt","inflight","maxConcurrency"]},"description":"The processes currently connected for a connected agent: hostname, user, pid, SDK and how many calls each has in flight. Empty for every other kind."},"selectable":{"type":"boolean","description":"Whether the credential making this request can run simulations against the agent. False for a personal development agent that belongs to somebody else, which is listed all the same so it can be told apart from the other agents of the same name."},"notSelectableReason":{"type":["string","null"],"enum":["owned_by_another_person",null],"description":"Why the agent cannot be run by this credential. Null when it can."},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"platformUrl":{"type":"string","format":"uri"}},"required":["id","name","type","config","environment","ownerUserId","hostLabel","lastSeenAt","parameters","owner","status","instances","selectable","notSelectableReason","createdAt","updatedAt","platformUrl"]}}}}},"description":"Update an agent: any of name, type, configuration and workflow. The update is partial under PATCH and PUT alike. A connected agent takes no edit and answers 422 agent_register_only.","tags":["Agents"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1},"required":true,"description":"The agent id."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"type":{"type":"string","enum":["signature","code","workflow","http","connected","voice"],"description":"The kind of agent to write. A connected agent is registered from code by the SDK, so \"connected\" is refused with agent_register_only."},"config":{"type":"object","additionalProperties":{}},"workflowId":{"type":["string","null"]}}}}}},"security":[{"project_api_key":[]}]},"put":{"operationId":"replaceAgent","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"type":"string","enum":["signature","code","workflow","http","connected","voice"],"description":"The kind of agent. A connected agent is registered from code by the SDK and cannot be created or reconfigured through this API."},"config":{"type":["object","null"],"additionalProperties":{}},"environment":{"type":["string","null"],"description":"The environment a connected agent registered with, for example production or development. Null for every other kind."},"ownerUserId":{"type":["string","null"],"description":"The user a personal development agent belongs to. Only that user can run simulations against it. Null when the agent is shared."},"hostLabel":{"type":["string","null"],"description":"The machine a development agent registered from with a project or service key. Null when the agent is personal or shared."},"lastSeenAt":{"type":["string","null"],"description":"When an instance of a connected agent was last connected. Null for every other kind."},"parameters":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","pattern":"^[A-Za-z_][A-Za-z0-9_]*$","minLength":1,"maxLength":64},"description":{"type":"string","maxLength":500},"defaultValue":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"secret":{"type":"boolean"},"type":{"type":"string","enum":["string","number","boolean"]},"options":{"type":"array","items":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"maxItems":50},"required":{"type":"boolean"}},"required":["name"]},"description":"The run parameters a connected agent declares from its function signature: name, type, options, default and description. Empty for every other kind."},"owner":{"type":["object","null"],"properties":{"userId":{"type":"string"},"name":{"type":["string","null"]}},"required":["userId","name"],"description":"The person a personal development agent belongs to. Null when the agent is shared or host-scoped."},"status":{"type":"string","enum":["online","offline"],"description":"online while at least one process running the connected agent is connected; offline otherwise, and always for every other kind."},"instances":{"type":"array","items":{"type":"object","properties":{"instanceId":{"type":"string"},"hostname":{"type":"string"},"username":{"type":"string"},"pid":{"type":"number"},"label":{"type":["string","null"]},"sdk":{"type":"object","properties":{"name":{"type":"string"},"version":{"type":"string"},"language":{"type":"string"}},"required":["name","version","language"]},"connectedAt":{"type":"string"},"inflight":{"type":"number"},"maxConcurrency":{"type":"number"}},"required":["instanceId","hostname","username","pid","label","sdk","connectedAt","inflight","maxConcurrency"]},"description":"The processes currently connected for a connected agent: hostname, user, pid, SDK and how many calls each has in flight. Empty for every other kind."},"selectable":{"type":"boolean","description":"Whether the credential making this request can run simulations against the agent. False for a personal development agent that belongs to somebody else, which is listed all the same so it can be told apart from the other agents of the same name."},"notSelectableReason":{"type":["string","null"],"enum":["owned_by_another_person",null],"description":"Why the agent cannot be run by this credential. Null when it can."},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"platformUrl":{"type":"string","format":"uri"}},"required":["id","name","type","config","environment","ownerUserId","hostLabel","lastSeenAt","parameters","owner","status","instances","selectable","notSelectableReason","createdAt","updatedAt","platformUrl"]}}}}},"description":"Update an agent: any of name, type, configuration and workflow. The update is partial under PATCH and PUT alike. A connected agent takes no edit and answers 422 agent_register_only.","tags":["Agents"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1},"required":true,"description":"The agent id."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"type":{"type":"string","enum":["signature","code","workflow","http","connected","voice"],"description":"The kind of agent to write. A connected agent is registered from code by the SDK, so \"connected\" is refused with agent_register_only."},"config":{"type":"object","additionalProperties":{}},"workflowId":{"type":["string","null"]}}}}}},"security":[{"project_api_key":[]}]},"delete":{"operationId":"archiveAgent","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"type":"string","enum":["signature","code","workflow","http","connected","voice"]},"archivedAt":{"type":["string","null"]}},"required":["id","name","type","archivedAt"]}}}}},"description":"Archive an agent. It leaves the list and its runs stay. A connected agent that registers again restores its row.","tags":["Agents"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1},"required":true,"description":"The agent id."}],"security":[{"project_api_key":[]}]}},"/api/v1/agents/{id}/test":{"post":{"operationId":"testAgent","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"scenarioRunId":{"type":"string","description":"The run to follow; open it in the simulations run drawer."},"batchRunId":{"type":"string","description":"The batch the run belongs to."},"setId":{"type":"string","description":"The internal set that holds agent test runs."}},"required":["scenarioRunId","batchRunId","setId"]}}}},"403":{"description":"The agent is a personal development agent of someone else"},"404":{"description":"No agent with that id in this project"},"422":{"description":"The agent cannot be tested as it is set up"},"503":{"description":"No process is holding the connected agent right now"}},"description":"Run one scripted scenario against an agent: the user sends \"ping\", the agent answers, and the run succeeds when the answer arrives. No model is used, and no scenario, run plan or test suite is added to the project. Answers at once with the run ids; the run itself is asynchronous.","tags":["Agents"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1},"required":true,"description":"The agent id."}],"security":[{"project_api_key":[]}]}},"/api/v1/agents/{id}/call":{"post":{"operationId":"callConnectedAgent","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"output":{"anyOf":[{"type":"string"},{"type":"object","properties":{"role":{"type":"string","minLength":1}},"required":["role"],"additionalProperties":true},{"type":"array","items":{"type":"object","properties":{"role":{"type":"string","minLength":1}},"required":["role"],"additionalProperties":true}}],"description":"What the function answered: text, one message, or a list of messages."},"session":{"description":"The agent's per-conversation memory, to send on the next turn."},"instance":{"type":"object","properties":{"hostname":{"type":"string"},"label":{"type":["string","null"]}},"required":["hostname","label"]},"durationMs":{"type":"number"}},"required":["output","instance","durationMs"]}}}},"404":{"description":"No connected agent with that id in this project"},"429":{"description":"Every instance is busy; Retry-After says when to try again","headers":{"Retry-After":{"description":"How many seconds to wait before the turn is sent again. Rounded up from the wait the platform picked.","schema":{"type":"string"}}}},"503":{"description":"No instance of the agent is connected"}},"description":"Send one conversation turn to a connected agent and get its answer. The agent must be online: a process running the decorated function must be connected.","tags":["Agents"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1},"required":true,"description":"The connected agent id."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"messages":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string","minLength":1}},"required":["role"],"additionalProperties":true},"description":"The whole conversation so far, OpenAI style."},"newMessages":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string","minLength":1}},"required":["role"],"additionalProperties":true},"description":"The messages added since the agent's last turn. Defaults to the last message."},"threadId":{"type":"string","maxLength":255,"description":"The conversation id. Turns of one conversation share it; a new id starts a new one."},"params":{"type":"object","propertyNames":{"type":"string","pattern":"^[A-Za-z_][A-Za-z0-9_]*$"},"additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"}]},"description":"Run parameter values by name, as JSON scalars."},"session":{"description":"The session the agent returned on its previous turn of this conversation, echoed back as is."},"traceparent":{"type":"string","maxLength":255,"description":"The W3C trace context the agent adopts, so its spans join this turn's trace."},"run":{"type":"object","properties":{"scenarioRunId":{"type":"string"},"scenarioName":{"type":"string"},"batchRunId":{"type":"string"}},"description":"The simulation run this turn belongs to, if any."}},"required":["messages"]}}}},"security":[{"project_api_key":[]}]}},"/api/api-keys":{"get":{"operationId":"listApiKeys","summary":"List API keys","description":"List all API keys owned by the authenticated user in this organization. Requires organization:view permission.","security":[{"admin_api_key":[]}],"responses":{"200":{"description":"List of API keys","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ApiKeyInfo"}}}}}}},"401":{"description":"Invalid or missing API key token"},"403":{"description":"Insufficient permissions (requires organization:view)"}}},"post":{"operationId":"createApiKey","summary":"Create an API key","description":"Create a new API key. For service keys, pass keyType:\"service\". Optionally scope to specific projects via projectIds (ADMIN on each). Omit projectIds for full org access. Pass assignedToUserId to mint the key for another member, and permissionMode:\"restricted\" with a permissions list to grant exactly those permissions. Minting a service key or a key for another member requires organization admin rights. The plaintext token is returned once — store it securely.","security":[{"admin_api_key":[]}],"responses":{"201":{"description":"API key created. The token field contains the plaintext key — it is only shown once.","content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","description":"Plaintext API key token (sk-lw-...). Store securely — shown only once."},"apiKey":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}}}}}}}},"401":{"description":"Invalid or missing API key token"},"403":{"description":"Requested binding exceeds the creator's own permissions, or the scope does not belong to this organization (api_key_scope_violation); a service key or a key for another member was requested without organization admin rights (insufficient_permissions)"},"422":{"description":"Validation error, for example a missing name or empty bindings (validation_error), or a name LangWatch reserves for its own keys (api_key_reserved_name)"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"keyType":{"type":"string","enum":["personal","service"],"default":"personal","description":"A personal key acts as the user who created it and needs explicit bindings. A service key is not tied to a user."},"name":{"type":"string","minLength":1,"maxLength":100,"description":"Human-readable name for this key"},"description":{"type":"string","maxLength":500},"expiresAt":{"type":"string","description":"ISO 8601 timestamp after which the key stops working"},"assignedToUserId":{"type":"string","minLength":1,"description":"Organization admins only: the member who owns the key and whose access caps it. Defaults to the caller."},"permissionMode":{"type":"string","enum":["all","readonly","restricted"],"description":"'all' and 'readonly' take their meaning from the bindings alone; 'restricted' additionally requires an explicit permissions list.","default":"all"},"permissions":{"type":"array","items":{"type":"string"},"description":"Restricted mode only: the exact resource:action permissions the key's CUSTOM bindings grant."},"bindings":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string","enum":["ADMIN","MEMBER","VIEWER","CUSTOM"],"description":"CUSTOM grants exactly the listed permissions and requires permissionMode 'restricted'."},"scopeType":{"type":"string","enum":["ORGANIZATION","TEAM","PROJECT"]},"scopeId":{"type":"string","minLength":1}},"required":["role","scopeType","scopeId"]},"maxItems":20,"description":"What this key may do, and where. Required for a personal key."},"projectIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":50,"description":"Service keys only: restricts the key to these projects"}},"required":["name"]}}}}}},"/api/api-keys/{id}":{"get":{"operationId":"getApiKey","summary":"Get an API key","description":"Read one API key by id, including its role bindings, permission mode and explicit permissions. Returns your own keys; organization admins may read any key in the organization. The secret is never returned. An id that does not exist, belongs to another organization, or belongs to another member all answer 404 api_key_not_found, so the response cannot be used to probe for keys.","security":[{"admin_api_key":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"API key ID"}],"responses":{"200":{"description":"The API key","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"keyType":{"type":"string","enum":["personal","service"]},"assignedToUserId":{"type":"string","nullable":true,"description":"The member who owns the key; null for a service key."},"createdByUserId":{"type":"string","nullable":true},"permissionMode":{"type":"string","enum":["all","readonly","restricted"]},"permissions":{"type":"array","items":{"type":"string"},"description":"The resource:action permissions a restricted key grants. Empty for the other modes."},"createdAt":{"type":"string","format":"date-time"},"expiresAt":{"type":"string","format":"date-time","nullable":true},"lastUsedAt":{"type":"string","format":"date-time","nullable":true},"revokedAt":{"type":"string","format":"date-time","nullable":true},"roleBindings":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"role":{"type":"string","enum":["ADMIN","MEMBER","VIEWER","CUSTOM"]},"scopeType":{"type":"string","enum":["ORGANIZATION","TEAM","PROJECT"]},"scopeId":{"type":"string"}}}},"bindings":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string","enum":["ADMIN","MEMBER","VIEWER","CUSTOM"]},"scopeType":{"type":"string","enum":["ORGANIZATION","TEAM","PROJECT"]},"scopeId":{"type":"string"}}}}}}}}},"401":{"description":"Invalid or missing API key token"},"403":{"description":"Insufficient permissions (requires organization:view)"},"404":{"description":"API key not found (api_key_not_found)"}}},"patch":{"operationId":"updateApiKey","summary":"Update an API key","description":"Update an API key's name, description, permission mode, permissions or bindings. Every field is optional; bindings are replaced outright, and the response is exactly what a subsequent GET returns. You may update your own keys; organization admins may update any key in the organization. Bindings can never exceed the access of the member the key belongs to. The token itself never changes.","security":[{"admin_api_key":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"API key ID"}],"responses":{"200":{"description":"The updated API key","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"keyType":{"type":"string","enum":["personal","service"]},"assignedToUserId":{"type":"string","nullable":true,"description":"The member who owns the key; null for a service key."},"createdByUserId":{"type":"string","nullable":true},"permissionMode":{"type":"string","enum":["all","readonly","restricted"]},"permissions":{"type":"array","items":{"type":"string"},"description":"The resource:action permissions a restricted key grants. Empty for the other modes."},"createdAt":{"type":"string","format":"date-time"},"expiresAt":{"type":"string","format":"date-time","nullable":true},"lastUsedAt":{"type":"string","format":"date-time","nullable":true},"revokedAt":{"type":"string","format":"date-time","nullable":true},"roleBindings":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"role":{"type":"string","enum":["ADMIN","MEMBER","VIEWER","CUSTOM"]},"scopeType":{"type":"string","enum":["ORGANIZATION","TEAM","PROJECT"]},"scopeId":{"type":"string"}}}},"bindings":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string","enum":["ADMIN","MEMBER","VIEWER","CUSTOM"]},"scopeType":{"type":"string","enum":["ORGANIZATION","TEAM","PROJECT"]},"scopeId":{"type":"string"}}}}}}}}},"401":{"description":"Invalid or missing API key token"},"403":{"description":"Insufficient permissions (requires organization:manage), the requested binding exceeds the key owner's own permissions, or the scope does not belong to this organization (api_key_scope_violation)"},"404":{"description":"API key not found, or not yours to edit (api_key_not_found)"},"409":{"description":"API key is already revoked (api_key_already_revoked)"},"422":{"description":"Validation error, for example restricted mode without a permissions list (validation_error)"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100},"description":{"type":["string","null"],"maxLength":500},"permissionMode":{"type":"string","enum":["all","readonly","restricted"],"description":"'all' and 'readonly' take their meaning from the bindings alone; 'restricted' additionally requires an explicit permissions list."},"permissions":{"type":"array","items":{"type":"string"},"description":"Restricted mode only: the exact resource:action permissions the key's CUSTOM bindings grant."},"bindings":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string","enum":["ADMIN","MEMBER","VIEWER","CUSTOM"],"description":"CUSTOM grants exactly the listed permissions and requires permissionMode 'restricted'."},"scopeType":{"type":"string","enum":["ORGANIZATION","TEAM","PROJECT"]},"scopeId":{"type":"string","minLength":1}},"required":["role","scopeType","scopeId"]},"minItems":1,"maxItems":20,"description":"Replaces the key's bindings outright. Whatever is accepted here is exactly what a subsequent GET returns."}}}}}}},"delete":{"operationId":"revokeApiKey","summary":"Revoke an API key","description":"Revoke (soft-delete) an API key. Revoked keys can no longer authenticate. Requires organization:manage permission.","security":[{"admin_api_key":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"API key ID"}],"responses":{"200":{"description":"API key revoked successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}}}}}},"401":{"description":"Invalid or missing API key token"},"403":{"description":"Not authorized to revoke this API key, which belongs to another member (api_key_not_owned)"},"404":{"description":"API key not found (api_key_not_found)"},"409":{"description":"API key is already revoked (api_key_already_revoked)"}}}},"/api/analytics/timeseries":{"post":{"operationId":"postApiAnalyticsTimeseries","description":"Query analytics timeseries data with metrics, aggregations, and filters","responses":{"200":{"description":"Timeseries analytics data with current and previous periods","content":{"application/json":{"schema":{"type":"object","properties":{"currentPeriod":{"type":"array","items":{"type":"object","additionalProperties":{}}},"previousPeriod":{"type":"array","items":{"type":"object","additionalProperties":{}}}},"required":["currentPeriod","previousPeriod"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"startDate":{"anyOf":[{"type":"number"},{"type":"string"}]},"endDate":{"anyOf":[{"type":"number"},{"type":"string"}]},"query":{"type":"string"},"filters":{"type":"object","properties":{"topics.topics":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"topics.subtopics":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"metadata.user_id":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"metadata.thread_id":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"metadata.customer_id":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"metadata.labels":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"metadata.key":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"metadata.value":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"metadata.prompt_ids":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"traces.origin":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"traces.error":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"traces.name":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"spans.type":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"spans.model":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.evaluator_id":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.evaluator_id.guardrails_only":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.evaluator_id.has_passed":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.evaluator_id.has_score":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.evaluator_id.has_label":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.passed":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.score":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.state":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.label":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"events.event_type":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"events.metrics.key":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"events.metrics.value":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"events.event_details.key":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"annotations.hasAnnotation":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]}},"additionalProperties":false,"default":{}},"traceIds":{"type":"array","items":{"type":"string"}},"negateFilters":{"type":"boolean"},"excludeOrigins":{"type":"array","items":{"type":"string"}},"series":{"type":"array","items":{"type":"object","properties":{"metric":{"type":"string","enum":["metadata.trace_id","metadata.user_id","metadata.thread_id","metadata.span_type","sentiment.thumbs_up_down","performance.completion_time","performance.first_token","performance.total_cost","performance.cost_billed","performance.cost_non_billed","performance.prompt_tokens","performance.completion_tokens","performance.cache_read_tokens","performance.cache_write_tokens","performance.reasoning_tokens","performance.total_processed_tokens","performance.total_tokens","performance.tokens_per_second","events.event_type","events.event_score","events.event_details","evaluations.evaluation_score","evaluations.evaluation_pass_rate","evaluations.evaluation_runs","threads.average_duration_per_thread"]},"key":{"type":"string"},"subkey":{"type":"string"},"aggregation":{"type":"string","enum":["terms","cardinality","avg","sum","min","max","median","p99","p95","p90"]},"pipeline":{"type":"object","properties":{"field":{"type":"string","enum":["trace_id","user_id","thread_id","customer_id"]},"aggregation":{"type":"string","enum":["sum","avg","min","max"]}},"required":["field","aggregation"]},"filters":{"type":"object","properties":{"topics.topics":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"topics.subtopics":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"metadata.user_id":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"metadata.thread_id":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"metadata.customer_id":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"metadata.labels":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"metadata.key":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"metadata.value":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"metadata.prompt_ids":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"traces.origin":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"traces.error":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"traces.name":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"spans.type":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"spans.model":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.evaluator_id":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.evaluator_id.guardrails_only":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.evaluator_id.has_passed":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.evaluator_id.has_score":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.evaluator_id.has_label":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.passed":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.score":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.state":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.label":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"events.event_type":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"events.metrics.key":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"events.metrics.value":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"events.event_details.key":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"annotations.hasAnnotation":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]}},"additionalProperties":false},"asPercent":{"type":"boolean"}},"required":["metric","aggregation"]}},"groupBy":{"type":"string","enum":["topics.topics","traces.trace_name","metadata.user_id","metadata.thread_id","metadata.customer_id","metadata.labels","metadata.model","metadata.span_type","sentiment.thumbs_up_down","events.event_type","evaluations.evaluation_passed","evaluations.evaluation_label","evaluations.evaluation_processing_state","error.has_error"]},"groupByKey":{"type":"string"},"timeScale":{"anyOf":[{"type":"string","const":"full"},{"type":"integer"}]},"timeZone":{"type":"string"}},"required":["startDate","endDate","series","timeZone"]}}}},"security":[{"project_api_key":[]}]}},"/api/v1/projects/{projectId}/analytics/charts":{"get":{"operationId":"getApiV1ProjectsByProjectIdAnalyticsCharts","summary":"List saved workbench charts","description":"Lists every saved LangWatchQL chart in this project, each with the statement it runs, the parameter values it was saved with and the Vega-Lite specification that draws it. Charts built with the chart builder are a different kind and are not listed here.","tags":["Analytics / LangWatchQL"],"responses":{"200":{"description":"The project's saved workbench charts","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"definition":{"type":"object","properties":{"version":{"type":"number"},"sql":{"type":"string"},"parameters":{"type":"object","additionalProperties":{}},"vegaLiteSpec":{"type":"object","additionalProperties":{}}},"required":["version","sql","parameters"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"platformUrl":{"type":"string"},"dashboardId":{"type":["string","null"]},"gridColumn":{"type":"integer"},"gridRow":{"type":"integer"},"colSpan":{"type":"integer"},"rowSpan":{"type":"integer"}},"required":["id","name","definition","createdAt","updatedAt","platformUrl","dashboardId","gridColumn","gridRow","colSpan","rowSpan"]}}},"required":["data"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"projectId","required":true}],"security":[{"project_api_key":[]}]},"post":{"operationId":"postApiV1ProjectsByProjectIdAnalyticsCharts","summary":"Save a workbench chart","description":"Saves a LangWatchQL statement, its bound parameter values and an optional Vega-Lite specification as one chart. The statement is validated by the LangWatchQL analytics SQL validator against this key's own permissions, and the specification by the visualization policy, before anything is written — a chart that could not be run or drawn is refused rather than stored.","tags":["Analytics / LangWatchQL"],"responses":{"201":{"description":"The chart was saved","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"definition":{"type":"object","properties":{"version":{"type":"number"},"sql":{"type":"string"},"parameters":{"type":"object","additionalProperties":{}},"vegaLiteSpec":{"type":"object","additionalProperties":{}}},"required":["version","sql","parameters"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"platformUrl":{"type":"string"},"dashboardId":{"type":["string","null"]},"gridColumn":{"type":"integer"},"gridRow":{"type":"integer"},"colSpan":{"type":"integer"},"rowSpan":{"type":"integer"}},"required":["id","name","definition","createdAt","updatedAt","platformUrl","dashboardId","gridColumn","gridRow","colSpan","rowSpan"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"definition":{}},"required":["name"]}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"projectId","required":true}],"security":[{"project_api_key":[]}]}},"/api/v1/projects/{projectId}/analytics/charts/{chartId}":{"get":{"operationId":"getApiV1ProjectsByProjectIdAnalyticsChartsByChartId","summary":"Get a saved workbench chart","description":"Returns one saved LangWatchQL chart with its statement, parameter values and specification. A chart saved in another project is reported as not found.","tags":["Analytics / LangWatchQL"],"responses":{"200":{"description":"The saved chart","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"definition":{"type":"object","properties":{"version":{"type":"number"},"sql":{"type":"string"},"parameters":{"type":"object","additionalProperties":{}},"vegaLiteSpec":{"type":"object","additionalProperties":{}}},"required":["version","sql","parameters"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"platformUrl":{"type":"string"},"dashboardId":{"type":["string","null"]},"gridColumn":{"type":"integer"},"gridRow":{"type":"integer"},"colSpan":{"type":"integer"},"rowSpan":{"type":"integer"}},"required":["id","name","definition","createdAt","updatedAt","platformUrl","dashboardId","gridColumn","gridRow","colSpan","rowSpan"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"404":{"description":"No chart with this id in this project","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"projectId","required":true},{"schema":{"type":"string"},"in":"path","name":"chartId","required":true}],"security":[{"project_api_key":[]}]},"patch":{"operationId":"patchApiV1ProjectsByProjectIdAnalyticsChartsByChartId","summary":"Update a saved workbench chart","description":"Replaces a saved chart's name, its definition, or both. A definition offered here passes exactly the validators a save passes, resolved against this key's current permissions — so a chart cannot be edited into naming a column the caller may no longer read. A request carrying neither field is refused.","tags":["Analytics / LangWatchQL"],"responses":{"200":{"description":"The updated chart","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"definition":{"type":"object","properties":{"version":{"type":"number"},"sql":{"type":"string"},"parameters":{"type":"object","additionalProperties":{}},"vegaLiteSpec":{"type":"object","additionalProperties":{}}},"required":["version","sql","parameters"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"platformUrl":{"type":"string"},"dashboardId":{"type":["string","null"]},"gridColumn":{"type":"integer"},"gridRow":{"type":"integer"},"colSpan":{"type":"integer"},"rowSpan":{"type":"integer"}},"required":["id","name","definition","createdAt","updatedAt","platformUrl","dashboardId","gridColumn","gridRow","colSpan","rowSpan"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"404":{"description":"No chart with this id in this project","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"definition":{}},"minProperties":1}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"projectId","required":true},{"schema":{"type":"string"},"in":"path","name":"chartId","required":true}],"security":[{"project_api_key":[]}]},"delete":{"operationId":"deleteApiV1ProjectsByProjectIdAnalyticsChartsByChartId","summary":"Delete a saved workbench chart","description":"Deletes one saved LangWatchQL chart. Answers 204 with no body; deleting a chart that is not in this project is reported as not found.","tags":["Analytics / LangWatchQL"],"responses":{"204":{"description":"The chart was deleted"},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"404":{"description":"No chart with this id in this project","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"projectId","required":true},{"schema":{"type":"string"},"in":"path","name":"chartId","required":true}],"security":[{"project_api_key":[]}]}},"/api/v1/projects/{projectId}/analytics/charts/{chartId}/placement":{"put":{"operationId":"putApiV1ProjectsByProjectIdAnalyticsChartsByChartIdPlacement","summary":"Place a saved workbench chart on a dashboard","description":"Places one saved LangWatchQL chart on a dashboard in the same project, at the grid position supplied — or, when no grid row is given, at the next row free on that dashboard, counting charts of every kind. A dashboard that is not in this project is reported as not found, exactly like a chart that is not, and nothing is written.","tags":["Analytics / LangWatchQL"],"responses":{"200":{"description":"The chart, now placed","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"definition":{"type":"object","properties":{"version":{"type":"number"},"sql":{"type":"string"},"parameters":{"type":"object","additionalProperties":{}},"vegaLiteSpec":{"type":"object","additionalProperties":{}}},"required":["version","sql","parameters"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"platformUrl":{"type":"string"},"dashboardId":{"type":["string","null"]},"gridColumn":{"type":"integer"},"gridRow":{"type":"integer"},"colSpan":{"type":"integer"},"rowSpan":{"type":"integer"}},"required":["id","name","definition","createdAt","updatedAt","platformUrl","dashboardId","gridColumn","gridRow","colSpan","rowSpan"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"404":{"description":"No chart with this id in this project","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"dashboardId":{"type":"string","minLength":1},"gridColumn":{"type":"integer"},"gridRow":{"type":"integer"},"colSpan":{"type":"integer"},"rowSpan":{"type":"integer"}},"required":["dashboardId"]}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"projectId","required":true},{"schema":{"type":"string"},"in":"path","name":"chartId","required":true}],"security":[{"project_api_key":[]}]},"delete":{"operationId":"deleteApiV1ProjectsByProjectIdAnalyticsChartsByChartIdPlacement","summary":"Remove a saved workbench chart from its dashboard","description":"Removes one saved LangWatchQL chart from whatever dashboard it is on, clearing its grid position along with the dashboard id. Idempotent: unplacing a chart that is not placed answers 204 all the same. The chart itself — its statement, parameter values and specification — is untouched.","tags":["Analytics / LangWatchQL"],"responses":{"204":{"description":"The chart is no longer on any dashboard"},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"404":{"description":"No chart with this id in this project","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"projectId","required":true},{"schema":{"type":"string"},"in":"path","name":"chartId","required":true}],"security":[{"project_api_key":[]}]}},"/api/v1/projects/{projectId}/analytics/dashboard-widgets":{"get":{"operationId":"getApiV1ProjectsByProjectIdAnalyticsDashboardWidgets","summary":"List dashboard widgets","description":"Lists every dashboard widget in this project, each with the React source file it renders and the named LangWatchQL queries it may run. Saved workbench charts and builder charts are different kinds and are not listed here.","tags":["Analytics / LangWatchQL"],"responses":{"200":{"description":"The project's dashboard widgets","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"definition":{"type":"object","properties":{"version":{"type":"number"},"code":{"type":"string"},"queries":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"sql":{"type":"string"},"parameters":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string","enum":["string","number","boolean"]},"default":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"}]}},"required":["name","type"]}}},"required":["name","sql"]}}},"required":["version","code","queries"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"platformUrl":{"type":"string"},"dashboardId":{"type":["string","null"]},"gridColumn":{"type":"integer"},"gridRow":{"type":"integer"},"colSpan":{"type":"integer"},"rowSpan":{"type":"integer"}},"required":["id","name","definition","createdAt","updatedAt","platformUrl","dashboardId","gridColumn","gridRow","colSpan","rowSpan"]}}},"required":["data"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"projectId","required":true}],"security":[{"project_api_key":[]}]},"post":{"operationId":"postApiV1ProjectsByProjectIdAnalyticsDashboardWidgets","summary":"Create a dashboard widget","description":"Saves a React source file and the named LangWatchQL queries it runs as one dashboard widget. The queries' shape is validated against the widget schema; their SQL is governed at run time by LW.query inside the sandbox, not at save.","tags":["Analytics / LangWatchQL"],"responses":{"201":{"description":"The widget was saved","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"definition":{"type":"object","properties":{"version":{"type":"number"},"code":{"type":"string"},"queries":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"sql":{"type":"string"},"parameters":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string","enum":["string","number","boolean"]},"default":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"}]}},"required":["name","type"]}}},"required":["name","sql"]}}},"required":["version","code","queries"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"platformUrl":{"type":"string"},"dashboardId":{"type":["string","null"]},"gridColumn":{"type":"integer"},"gridRow":{"type":"integer"},"colSpan":{"type":"integer"},"rowSpan":{"type":"integer"}},"required":["id","name","definition","createdAt","updatedAt","platformUrl","dashboardId","gridColumn","gridRow","colSpan","rowSpan"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"code":{"type":"string","minLength":1,"maxLength":200000},"queries":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","pattern":"^[A-Za-z_][A-Za-z0-9_]*$","minLength":1,"maxLength":64},"sql":{"type":"string","minLength":1,"maxLength":50000},"parameters":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","pattern":"^[A-Za-z_][A-Za-z0-9_]*$","minLength":1,"maxLength":64},"type":{"type":"string","enum":["string","number","boolean"]},"default":{"anyOf":[{"type":"string","maxLength":4000},{"type":"number"},{"type":"boolean"}]}},"required":["name","type"]},"maxItems":32}},"required":["name","sql"]},"maxItems":8}},"required":["name","code","queries"]}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"projectId","required":true}],"security":[{"project_api_key":[]}]}},"/api/v1/projects/{projectId}/analytics/dashboard-widgets/{widgetId}":{"get":{"operationId":"getApiV1ProjectsByProjectIdAnalyticsDashboardWidgetsByWidgetId","summary":"Get a dashboard widget","description":"Returns one dashboard widget with its React source and named queries. A widget saved in another project is reported as not found.","tags":["Analytics / LangWatchQL"],"responses":{"200":{"description":"The dashboard widget","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"definition":{"type":"object","properties":{"version":{"type":"number"},"code":{"type":"string"},"queries":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"sql":{"type":"string"},"parameters":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string","enum":["string","number","boolean"]},"default":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"}]}},"required":["name","type"]}}},"required":["name","sql"]}}},"required":["version","code","queries"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"platformUrl":{"type":"string"},"dashboardId":{"type":["string","null"]},"gridColumn":{"type":"integer"},"gridRow":{"type":"integer"},"colSpan":{"type":"integer"},"rowSpan":{"type":"integer"}},"required":["id","name","definition","createdAt","updatedAt","platformUrl","dashboardId","gridColumn","gridRow","colSpan","rowSpan"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"404":{"description":"No dashboard widget with this id in this project","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"projectId","required":true},{"schema":{"type":"string"},"in":"path","name":"widgetId","required":true}],"security":[{"project_api_key":[]}]},"patch":{"operationId":"patchApiV1ProjectsByProjectIdAnalyticsDashboardWidgetsByWidgetId","summary":"Update a dashboard widget","description":"Replaces a dashboard widget's name, its { code, queries } definition, or both. code and queries are rewritten together — the graph blob holds them as one — so a request that offers one without the other, or neither field at all, is refused.","tags":["Analytics / LangWatchQL"],"responses":{"200":{"description":"The updated widget","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"definition":{"type":"object","properties":{"version":{"type":"number"},"code":{"type":"string"},"queries":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"sql":{"type":"string"},"parameters":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string","enum":["string","number","boolean"]},"default":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"}]}},"required":["name","type"]}}},"required":["name","sql"]}}},"required":["version","code","queries"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"platformUrl":{"type":"string"},"dashboardId":{"type":["string","null"]},"gridColumn":{"type":"integer"},"gridRow":{"type":"integer"},"colSpan":{"type":"integer"},"rowSpan":{"type":"integer"}},"required":["id","name","definition","createdAt","updatedAt","platformUrl","dashboardId","gridColumn","gridRow","colSpan","rowSpan"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"404":{"description":"No dashboard widget with this id in this project","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"code":{"type":"string","minLength":1,"maxLength":200000},"queries":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","pattern":"^[A-Za-z_][A-Za-z0-9_]*$","minLength":1,"maxLength":64},"sql":{"type":"string","minLength":1,"maxLength":50000},"parameters":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","pattern":"^[A-Za-z_][A-Za-z0-9_]*$","minLength":1,"maxLength":64},"type":{"type":"string","enum":["string","number","boolean"]},"default":{"anyOf":[{"type":"string","maxLength":4000},{"type":"number"},{"type":"boolean"}]}},"required":["name","type"]},"maxItems":32}},"required":["name","sql"]},"maxItems":8}},"minProperties":1}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"projectId","required":true},{"schema":{"type":"string"},"in":"path","name":"widgetId","required":true}],"security":[{"project_api_key":[]}]},"delete":{"operationId":"deleteApiV1ProjectsByProjectIdAnalyticsDashboardWidgetsByWidgetId","summary":"Delete a dashboard widget","description":"Deletes one dashboard widget. Answers 204 with no body; deleting a widget that is not in this project is reported as not found.","tags":["Analytics / LangWatchQL"],"responses":{"204":{"description":"The widget was deleted"},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"404":{"description":"No dashboard widget with this id in this project","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"projectId","required":true},{"schema":{"type":"string"},"in":"path","name":"widgetId","required":true}],"security":[{"project_api_key":[]}]}},"/api/v1/projects/{projectId}/analytics/dashboard-widgets/{widgetId}/dashboard":{"post":{"operationId":"postApiV1ProjectsByProjectIdAnalyticsDashboardWidgetsByWidgetIdDashboard","summary":"Add a dashboard widget to a dashboard","description":"Assigns a dashboard widget to a dashboard. The widget is repositioned to the next free row on that dashboard; its size (colSpan/rowSpan) is preserved.","tags":["Analytics / LangWatchQL"],"responses":{"200":{"description":"The widget was added to the dashboard","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"definition":{"type":"object","properties":{"version":{"type":"number"},"code":{"type":"string"},"queries":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"sql":{"type":"string"},"parameters":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string","enum":["string","number","boolean"]},"default":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"}]}},"required":["name","type"]}}},"required":["name","sql"]}}},"required":["version","code","queries"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"platformUrl":{"type":"string"},"dashboardId":{"type":["string","null"]},"gridColumn":{"type":"integer"},"gridRow":{"type":"integer"},"colSpan":{"type":"integer"},"rowSpan":{"type":"integer"}},"required":["id","name","definition","createdAt","updatedAt","platformUrl","dashboardId","gridColumn","gridRow","colSpan","rowSpan"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"404":{"description":"No dashboard widget with this id in this project","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"dashboardId":{"type":"string","minLength":1}},"required":["dashboardId"]}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"projectId","required":true},{"schema":{"type":"string"},"in":"path","name":"widgetId","required":true}],"security":[{"project_api_key":[]}]}},"/api/v1/query":{"post":{"operationId":"postApiV1Query","summary":"Run a LangWatchQL query","description":"Executes one read-only LangWatchQL SELECT over the analytics views and returns typed columns, rows, execution statistics and diagnostics. The query runs as a restricted database identity scoped to the projects this key can read.\n\nDiagnostics are advisory and never reject a query. An empty diagnostics list means no known issue was detected. It is not proof that the answer is the one you meant.\n\nA projection may call the app functions the schema endpoint lists (`conversation`, `llm_readable_trace`, `llm_messages`, and so on). Those are computed by the application after the query, so they are allowed only as aliased entries in the top-level SELECT list; a call in WHERE, GROUP BY, ORDER BY, a join, a subquery or a nested expression is refused, and a UNION disqualifies both of its branches even where each reads as a top-level projection. A projection may also call the eval functions, which judge a text with a model and are charged for; their key is the text itself. A run that would need more distinct conversations, traces, spans or texts than the published cap answers 422 rather than a partial result, and a run whose texts would exceed the per-query token budget answers 422 before anything is sent.\n\nAny LangWatch API key — project, organization or personal — reaches every project it can read `analytics:view` on: an organization or personal key spans its projects, a project key its one. Rows from more than one project come back flagged with the `MULTI_PROJECT_RESULT` diagnostic — to read a single project, filter inside the statement with `WHERE TenantId = '<project id>'`.\n\nA statement that names no `LIMIT` is capped at 10,000 rows: that `LIMIT` is appended before the query runs. A statement whose own `LIMIT` asks for more is refused with `LIMIT_TOO_HIGH` — lower it and page the rest with `LIMIT`/`OFFSET` and an `ORDER BY`. When using `UNION`, every top-level branch must carry its own `LIMIT` clause of 10,000 rows or fewer, or the query is refused with `LIMIT_REQUIRED_PER_BRANCH`. A result whose body exceeds about 8,000,000 bytes is refused outright with `lwql_result_too_large`, never cut — select fewer columns or a smaller `LIMIT`.\n\nFailures answer with their real HTTP status (a refused query is 403, not 200) and this API's canonical error envelope — the same `code` and `meta` every other REST family publishes.","tags":["Query"],"responses":{"200":{"description":"The query ran. Columns, rows, execution statistics and diagnostics, scoped to the projects the key can read.","content":{"application/json":{"schema":{"type":"object","properties":{"columns":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string"}},"required":["name","type"]}},"rows":{"type":"array","items":{"type":"object","additionalProperties":{}}},"statistics":{"type":"object","properties":{"elapsedMs":{"type":"number"},"rowsRead":{"type":"number"},"bytesRead":{"type":"number"},"rowsReturned":{"type":"number"}},"required":["elapsedMs","rowsRead","bytesRead","rowsReturned"]},"followsTimeWindow":{"type":"boolean"},"followsGranularity":{"type":"boolean"},"granularitySeconds":{"type":"number"},"coarsenedFromSeconds":{"type":"number"},"diagnostics":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string","enum":["MULTI_PROJECT_RESULT","POSSIBLE_FANOUT","UNBOUNDED_TIME_RANGE","MISSING_TIME_BUCKETS","INCOMPLETE_COMPARISON_PERIOD","APP_FUNCTION_VALUE_TRUNCATED","APP_FUNCTION_UNRESOLVED_KEYS","APP_FUNCTION_RESULT_TRUNCATED","INSTANT_EVAL_SKIPPED"]},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}}},"required":["code","message"]}}},"required":["columns","rows","statistics","followsTimeWindow","followsGranularity","diagnostics"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sql":{"type":"string","minLength":1,"maxLength":50000},"parameters":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"null"}]}},"timeWindow":{"type":"object","properties":{"start":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"string","description":"A value already parsed into a native Date. A JSON request body cannot produce this shape — send a string or a number instead."}]},"end":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"string","description":"A value already parsed into a native Date. A JSON request body cannot produce this shape — send a string or a number instead."}]}},"required":["start","end"]},"granularitySeconds":{"anyOf":[{"type":"number","const":1},{"type":"number","const":60},{"type":"number","const":3600}]}},"required":["sql"]}}}},"security":[{"project_api_key":[]}]}},"/api/v1/query/schema":{"get":{"operationId":"getApiV1QuerySchema","summary":"Discover the queryable LangWatchQL schema","description":"Lists the LangWatchQL analytics views this key may query, with each column's type, description, the permissions that unlock it, and whether this caller holds them — plus each view's grain, join keys, partition-pruning time column, freshness and a runnable example query. It also lists, under `functions`, every function name a query may call.\n\nUnder `appFunctions` it lists the app functions a projection may call, each with its signature, the type and encoding of the value it returns, how many distinct keys one run may read, and the permissions it needs.\n\nScoped to the projects the credential can read and their permissions: a column or app function this key cannot read in every one of them is listed with `available: false` rather than hidden, so a caller can see what a wider key would unlock.\n\nAny LangWatch API key — project, organization or personal — reaches every project it can read `analytics:view` on: an organization or personal key spans its projects, a project key its one. Rows from more than one project come back flagged with the `MULTI_PROJECT_RESULT` diagnostic — to read a single project, filter inside the statement with `WHERE TenantId = '<project id>'`.","tags":["Query"],"responses":{"200":{"description":"The views and columns this key may query, with the permissions that unlock each one.","content":{"application/json":{"schema":{"type":"object","properties":{"database":{"type":"string"},"views":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"grain":{"type":"string"},"joinKeys":{"type":"array","items":{"type":"string"}},"timeColumn":{"type":"string"},"freshness":{"type":"string"},"columns":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string"},"description":{"type":"string"},"unit":{"type":["string","null"],"enum":["ms","USD","tokens","tokens/s",null]},"gates":{"type":"array","items":{"type":"string","enum":["input","output","costs"]}},"available":{"type":"boolean"}},"required":["name","type","description","unit","gates","available"]}},"exampleSql":{"type":"string"}},"required":["name","description","grain","joinKeys","timeColumn","freshness","columns","exampleSql"]}},"functions":{"type":"array","items":{"type":"string"}},"appFunctions":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"signature":{"type":"string"},"description":{"type":"string"},"kind":{"type":"string","enum":["extraction","eval"]},"returns":{"type":"string"},"encoding":{"type":"string","enum":["text","json"]},"keyKind":{"type":"string","enum":["trace","thread","span","text"]},"cap":{"type":"integer","exclusiveMinimum":0},"gates":{"type":"array","items":{"type":"string","enum":["input","output","costs"]}},"available":{"type":"boolean"},"exampleSql":{"type":"string"}},"required":["name","signature","description","kind","returns","encoding","keyKind","cap","gates","available","exampleSql"]}}},"required":["database","views","functions","appFunctions"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"security":[{"project_api_key":[]}]}},"/api/v1/query/reference":{"get":{"operationId":"getApiV1QueryReference","summary":"Discover both query languages","description":"Describes both query languages in one payload: LangWatchQL (SQL over the analytics views) with its schema, limits and endpoints, and the trace filter (a Lucene-flavored string over the trace list) with its syntax, its fields and their static value vocabularies, and the open-ended attribute namespaces.\n\nIt also carries worked examples in both languages and a table saying which language answers which kind of question. Every example is checked against the real validator and the real translator before it ships, so a published example parses and compiles; whether THIS key can run one is its own `available` flag.\n\nPure: it reads the catalogs and this key's own permissions, never the project's traces, so it answers from memory rather than from the database.\n\nIt answers `Cache-Control: private, no-store`, because the document is shaped by the calling credential: `available`, the embedded schema and the gated columns all differ between keys, and a cache keyed on the URL or the project would replay one key's document to another. Ask for it again rather than storing it.\n\nThe values a field actually holds change under you and are a separate call — `GET /api/traces/facets`.\n\nAn example this key cannot run is listed with `available: false` and keeps its `requires.gates`, so a caller can see which permission it needs.\n\nAny credential for the project may read it. The trace filter half is the traces family's vocabulary, so a key scoped to `traces:view` alone is answered rather than refused; for that key the LangWatchQL half arrives with `lwql.enabled: false` and an empty schema. `GET /api/v1/query/schema` is stricter and refuses that key outright, which is why this document withholds the catalog rather than repeating it.","tags":["Query"],"responses":{"200":{"description":"The LangWatchQL schema and limits, the trace filter's syntax and fields, worked examples in both languages, and which language answers which kind of question.","content":{"application/json":{"schema":{"type":"object","properties":{"version":{"type":"string"},"lwql":{"type":"object","properties":{"enabled":{"type":"boolean"},"schema":{"type":"object","properties":{"database":{"type":"string"},"views":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"grain":{"type":"string"},"joinKeys":{"type":"array","items":{"type":"string"}},"timeColumn":{"type":"string"},"freshness":{"type":"string"},"columns":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string"},"description":{"type":"string"},"unit":{"type":["string","null"],"enum":["ms","USD","tokens","tokens/s",null]},"gates":{"type":"array","items":{"type":"string","enum":["input","output","costs"]}},"available":{"type":"boolean"}},"required":["name","type","description","unit","gates","available"]}},"exampleSql":{"type":"string"}},"required":["name","description","grain","joinKeys","timeColumn","freshness","columns","exampleSql"]}},"functions":{"type":"array","items":{"type":"string"}},"appFunctions":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"signature":{"type":"string"},"description":{"type":"string"},"kind":{"type":"string","enum":["extraction","eval"]},"returns":{"type":"string"},"encoding":{"type":"string","enum":["text","json"]},"keyKind":{"type":"string","enum":["trace","thread","span","text"]},"cap":{"type":"integer","exclusiveMinimum":0},"gates":{"type":"array","items":{"type":"string","enum":["input","output","costs"]}},"available":{"type":"boolean"},"exampleSql":{"type":"string"}},"required":["name","signature","description","kind","returns","encoding","keyKind","cap","gates","available","exampleSql"]}}},"required":["database","views","functions","appFunctions"]},"limits":{"type":"object","properties":{"maxStatementLength":{"type":"number"},"maxRowsReturned":{"type":"number"},"maxResultBytes":{"type":"number"},"maxExecutionTimeSeconds":{"type":"number"},"pagination":{"type":"string"}},"required":["maxStatementLength","maxRowsReturned","maxResultBytes","maxExecutionTimeSeconds","pagination"]},"endpoints":{"type":"array","items":{"type":"object","properties":{"method":{"type":"string","enum":["GET","POST"]},"path":{"type":"string"},"description":{"type":"string"}},"required":["method","path","description"]}}},"required":["enabled","schema","limits","endpoints"]},"traceFilter":{"type":"object","properties":{"syntax":{"type":"string"},"fields":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"label":{"type":"string"},"valueType":{"type":"string","enum":["categorical","range","text","existence"]},"group":{"type":["string","null"]},"facetable":{"type":"boolean"},"knownValues":{"type":"array","items":{"type":"string"}}},"required":["name","label","valueType","group","facetable","knownValues"]}},"dynamicPrefixes":{"type":"array","items":{"type":"object","properties":{"prefix":{"type":"string"},"label":{"type":"string"},"description":{"type":"string"},"aliases":{"type":"array","items":{"type":"string"}}},"required":["prefix","label","description","aliases"]}},"endpoints":{"type":"array","items":{"type":"object","properties":{"method":{"type":"string","enum":["GET","POST"]},"path":{"type":"string"},"description":{"type":"string"}},"required":["method","path","description"]}}},"required":["syntax","fields","dynamicPrefixes","endpoints"]},"examples":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"intent":{"type":"string","enum":["triage","cost","latency","quality","conversations","discovery","export"]},"language":{"type":"string","enum":["lwql","trace-filter"]},"tags":{"type":"array","items":{"type":"string"}},"text":{"type":"string"},"parameters":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string"},"description":{"type":"string"}},"required":["name","type","description"]}},"requires":{"type":"object","properties":{"gates":{"type":"array","items":{"type":"string","enum":["input","output","costs"]}},"functions":{"type":"array","items":{"type":"string"}}},"required":["gates","functions"]},"available":{"type":"boolean"},"notes":{"type":"string"}},"required":["id","title","intent","language","tags","text","parameters","requires","available"]}},"decisionTable":{"type":"array","items":{"type":"object","properties":{"when":{"type":"string"},"use":{"type":"string"},"why":{"type":"string"}},"required":["when","use","why"]}}},"required":["version","lwql","traceFilter","examples","decisionTable"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"security":[{"project_api_key":[]}]}},"/api/coding-agent/sessions/{sessionId}/events":{"get":{"operationId":"getApiCodingAgentSessionsBySessionIdEvents","summary":"List coding agent session events","description":"List a coding-agent session's events (model calls, compactions, rate limits, tool runs, prompts) in time order, keyset-paginated. Pass the previous response's nextCursor to continue; filter with kinds (comma-separated).","parameters":[{"name":"sessionId","in":"path","required":true,"schema":{"type":"string"},"description":"The agent's own session id (session.id / conversation id)."},{"name":"kinds","in":"query","required":false,"schema":{"type":"string"},"description":"Comma-separated event kinds to include. Known kinds: model_call, compaction, rate_limit, api_error, retries_exhausted, tool_result, tool_decision, user_prompt, subagent_completed."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque keyset cursor from the previous response's nextCursor."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"default":500}},{"name":"from","in":"query","required":false,"schema":{"type":"integer"},"description":"Epoch ms lower bound on event time; with `to`, prunes storage partitions for faster reads."},{"name":"to","in":"query","required":false,"schema":{"type":"integer"},"description":"Epoch ms upper bound on event time."}],"responses":{"200":{"description":"One page of session events plus the cursor for the next page","content":{"application/json":{"schema":{"type":"object","properties":{"events":{"type":"array","items":{"type":"object","properties":{"sessionId":{"type":"string"},"timeUnixMs":{"type":"number"},"recordId":{"type":"string"},"eventKind":{"type":"string"},"agent":{"type":"string"},"sessionKeySource":{"type":"string"},"traceId":{"type":"string"},"spanId":{"type":"string"},"promptId":{"type":"string"},"querySource":{"type":"string"},"agentType":{"type":"string"},"eventSequence":{"type":"number"},"requestId":{"type":"string"},"model":{"type":"string"},"inputTokens":{"type":"number"},"outputTokens":{"type":"number"},"cacheReadTokens":{"type":"number"},"cacheCreationTokens":{"type":"number"},"costUsd":{"type":"number"},"durationMs":{"type":"number"},"ttftMs":{"type":"number"},"attempt":{"type":"number"},"speed":{"type":"string"},"stopReason":{"type":"string"},"preTokens":{"type":"number"},"postTokens":{"type":"number"},"compactionTrigger":{"type":"string"},"precomputeReuse":{"type":"string"},"statusCode":{"type":"string"},"errorType":{"type":"string"},"rateLimitCarrier":{"type":"string"},"retryDurationMs":{"type":"number"},"toolName":{"type":"string"},"success":{"type":"string"},"decision":{"type":"string"},"decisionSource":{"type":"string"},"toolInputBytes":{"type":"number"},"toolResultBytes":{"type":"number"},"promptChars":{"type":"number"},"totalTokens":{"type":"number"}},"required":["sessionId","timeUnixMs","recordId","eventKind","agent","sessionKeySource","traceId","spanId","promptId","querySource","agentType","eventSequence","requestId","model","inputTokens","outputTokens","cacheReadTokens","cacheCreationTokens","costUsd","durationMs","ttftMs","attempt","speed","stopReason","preTokens","postTokens","compactionTrigger","precomputeReuse","statusCode","errorType","rateLimitCarrier","retryDurationMs","toolName","success","decision","decisionSource","toolInputBytes","toolResultBytes","promptChars","totalTokens"]}},"nextCursor":{"type":["string","null"]}},"required":["events","nextCursor"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"security":[{"project_api_key":[]}]}},"/api/coding-agent/pull-request-usage":{"get":{"operationId":"getApiCodingAgentPullRequestUsage","summary":"Get pull request coding agent usage","description":"Assistant usage for one pull request: sessions, tokens and cost, grouped by contributor and agent, plus per-model totals, over the pull request's whole lifetime rather than a time window. Every row and the totals split cost three ways: the part priced per token, the part a bundled subscription already covers, and the list-price total of both. Per-model totals carry the list price only. Cost is calculated from the tokens the agent reported and LangWatch's model prices, so it estimates spend rather than restating a provider invoice. Requires a personal-project API key; rows appear only for projects the calling user may view, and cost only for those they may price. Prefer `GET /api/v1/coding-agent/pull-request-usage`, which answers the same question with an organization API key alone and needs no X-Project-Id header.","parameters":[{"name":"repository","in":"query","required":true,"schema":{"type":"string"},"description":"The repository as \"owner/name\"."},{"name":"pullRequest","in":"query","required":true,"schema":{"type":"integer"},"description":"The pull request number."},{"name":"host","in":"query","required":false,"schema":{"type":"string","default":"github.com"}}],"responses":{"200":{"description":"The pull request's usage rollup","content":{"application/json":{"schema":{"type":"object","properties":{"pullRequest":{"type":"object","properties":{"repositoryHost":{"type":"string"},"repositoryFullName":{"type":"string"},"prNumber":{"type":"number"},"headBranch":{"type":"string"},"htmlUrl":{"type":"string"},"state":{"type":"string"},"isDraft":{"type":"boolean"},"authorLogin":{"type":["string","null"]},"prCreatedAtMs":{"type":"number"},"prClosedAtMs":{"type":["number","null"]},"prMergedAtMs":{"type":["number","null"]}},"required":["repositoryHost","repositoryFullName","prNumber","headBranch","htmlUrl","state","isDraft","authorLogin","prCreatedAtMs","prClosedAtMs","prMergedAtMs"]},"rows":{"type":"array","items":{"type":"object","properties":{"projectId":{"type":"string"},"projectSlug":{"type":"string"},"contributorLabel":{"type":"string"},"contributorIsProject":{"type":"boolean"},"agent":{"type":"string"},"models":{"type":"array","items":{"type":"string"}},"sessionsCount":{"type":"number"},"inputTokens":{"type":"number"},"outputTokens":{"type":"number"},"cacheReadTokens":{"type":"number"},"cacheCreationTokens":{"type":"number"},"totalTokens":{"type":"number"},"costUsd":{"type":["number","null"]},"billedCostUsd":{"type":["number","null"]},"nonBilledCostUsd":{"type":["number","null"]}},"required":["projectId","projectSlug","contributorLabel","contributorIsProject","agent","models","sessionsCount","inputTokens","outputTokens","cacheReadTokens","cacheCreationTokens","totalTokens","costUsd","billedCostUsd","nonBilledCostUsd"]}},"totals":{"type":"object","properties":{"sessionsCount":{"type":"number"},"inputTokens":{"type":"number"},"outputTokens":{"type":"number"},"cacheReadTokens":{"type":"number"},"cacheCreationTokens":{"type":"number"},"totalTokens":{"type":"number"},"costUsd":{"type":["number","null"]},"billedCostUsd":{"type":["number","null"]},"nonBilledCostUsd":{"type":["number","null"]}},"required":["sessionsCount","inputTokens","outputTokens","cacheReadTokens","cacheCreationTokens","totalTokens","costUsd","billedCostUsd","nonBilledCostUsd"]},"modelBreakdown":{"type":"array","items":{"type":"object","properties":{"model":{"type":"string"},"inputTokens":{"type":"number"},"outputTokens":{"type":"number"},"cacheReadTokens":{"type":"number"},"cacheCreationTokens":{"type":"number"},"totalTokens":{"type":"number"},"costUsd":{"type":["number","null"]},"tokensKnown":{"type":"boolean"}},"required":["model","inputTokens","outputTokens","cacheReadTokens","cacheCreationTokens","totalTokens","costUsd","tokensKnown"]}}},"required":["pullRequest","rows","totals","modelBreakdown"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"security":[{"project_api_key":[]}]}},"/api/v1/coding-agent/pull-request-usage":{"get":{"operationId":"getPullRequestUsage","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"pullRequest":{"type":"object","properties":{"repositoryHost":{"type":"string"},"repositoryFullName":{"type":"string"},"prNumber":{"type":"number"},"headBranch":{"type":"string"},"htmlUrl":{"type":"string"},"state":{"type":"string"},"isDraft":{"type":"boolean"},"authorLogin":{"type":["string","null"]},"prCreatedAtMs":{"type":"number"},"prClosedAtMs":{"type":["number","null"]},"prMergedAtMs":{"type":["number","null"]}},"required":["repositoryHost","repositoryFullName","prNumber","headBranch","htmlUrl","state","isDraft","authorLogin","prCreatedAtMs","prClosedAtMs","prMergedAtMs"]},"rows":{"type":"array","items":{"type":"object","properties":{"projectId":{"type":"string"},"projectSlug":{"type":"string"},"contributorLabel":{"type":"string"},"contributorIsProject":{"type":"boolean"},"agent":{"type":"string"},"models":{"type":"array","items":{"type":"string"}},"sessionsCount":{"type":"number"},"inputTokens":{"type":"number"},"outputTokens":{"type":"number"},"cacheReadTokens":{"type":"number"},"cacheCreationTokens":{"type":"number"},"totalTokens":{"type":"number"},"costUsd":{"type":["number","null"]},"billedCostUsd":{"type":["number","null"]},"nonBilledCostUsd":{"type":["number","null"]}},"required":["projectId","projectSlug","contributorLabel","contributorIsProject","agent","models","sessionsCount","inputTokens","outputTokens","cacheReadTokens","cacheCreationTokens","totalTokens","costUsd","billedCostUsd","nonBilledCostUsd"]}},"totals":{"type":"object","properties":{"sessionsCount":{"type":"number"},"inputTokens":{"type":"number"},"outputTokens":{"type":"number"},"cacheReadTokens":{"type":"number"},"cacheCreationTokens":{"type":"number"},"totalTokens":{"type":"number"},"costUsd":{"type":["number","null"]},"billedCostUsd":{"type":["number","null"]},"nonBilledCostUsd":{"type":["number","null"]}},"required":["sessionsCount","inputTokens","outputTokens","cacheReadTokens","cacheCreationTokens","totalTokens","costUsd","billedCostUsd","nonBilledCostUsd"]},"modelBreakdown":{"type":"array","items":{"type":"object","properties":{"model":{"type":"string"},"inputTokens":{"type":"number"},"outputTokens":{"type":"number"},"cacheReadTokens":{"type":"number"},"cacheCreationTokens":{"type":"number"},"totalTokens":{"type":"number"},"costUsd":{"type":["number","null"]},"tokensKnown":{"type":"boolean"}},"required":["model","inputTokens","outputTokens","cacheReadTokens","cacheCreationTokens","totalTokens","costUsd","tokensKnown"]}}},"required":["pullRequest","rows","totals","modelBreakdown"]}}}}},"description":"Assistant usage for one pull request: sessions, tokens and cost, grouped by contributor and agent, plus per-model totals, over the pull request's whole lifetime rather than a time window. Every row and the totals split cost three ways: the part priced per token, the part a bundled subscription already covers, and the list-price total of both. Per-model totals carry the list price only. Cost is calculated from the tokens the agent reported and LangWatch's model prices, so it estimates spend rather than restating a provider invoice. Authenticate with an organization API key and nothing else: no project id is sent anywhere. A key created for you reads with your own access; an organization service key, such as one a continuous integration job holds, reads with the access its bindings grant. Rows appear only for projects the key may view, and cost only for those it may price.","summary":"Get pull request usage","tags":["Coding Agents"],"parameters":[{"in":"query","name":"repository","schema":{"type":"string","pattern":"^[^/\\s]+\\/[^/\\s]+$"},"required":true,"description":"The repository as \"owner/name\"."},{"in":"query","name":"pullRequest","schema":{"type":"integer","exclusiveMinimum":0},"required":true,"description":"The pull request number."},{"in":"query","name":"host","schema":{"type":"string","minLength":1,"default":"github.com"},"description":"The GitHub host. Defaults to this instance's configured GitHub host, which is github.com unless an operator named a GitHub Enterprise Server."}],"security":[{"admin_api_key":[]}]}},"/api/dashboards":{"get":{"operationId":"getApiDashboards","description":"List all dashboards for the project with graph counts","responses":{},"security":[{"project_api_key":[]}]},"post":{"operationId":"postApiDashboards","description":"Create a new dashboard","responses":{},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255}},"required":["name"]}}}},"security":[{"project_api_key":[]}]}},"/api/dashboards/reorder":{"put":{"operationId":"putApiDashboardsReorder","description":"Reorder dashboards by providing an ordered list of IDs","responses":{},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"dashboardIds":{"type":"array","items":{"type":"string","minLength":1},"minItems":1}},"required":["dashboardIds"]}}}},"security":[{"project_api_key":[]}]}},"/api/dashboards/{id}":{"get":{"operationId":"getApiDashboardsById","description":"Get a dashboard by its id, including its graphs","responses":{},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]},"patch":{"operationId":"patchApiDashboardsById","description":"Rename a dashboard","responses":{},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255}},"required":["name"]}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]},"delete":{"operationId":"deleteApiDashboardsById","description":"Delete a dashboard and its graphs (hard delete, cascade)","responses":{},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]}},"/api/dataset":{"get":{"operationId":"getApiDataset","description":"List all non-archived datasets for the project (paginated)","responses":{},"parameters":[{"in":"query","name":"page","schema":{"type":"integer","exclusiveMinimum":0,"default":1}},{"in":"query","name":"limit","schema":{"type":"integer","exclusiveMinimum":0,"maximum":1000,"default":50}}],"security":[{"project_api_key":[]}]},"post":{"operationId":"postApiDataset","description":"Create a new dataset","responses":{},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1},"columnTypes":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"type":{"anyOf":[{"type":"string","const":"string"},{"type":"string","const":"boolean"},{"type":"string","const":"number"},{"type":"string","const":"date"},{"type":"string","const":"list"},{"type":"string","const":"json"},{"type":"string","const":"spans"},{"type":"string","const":"rag_contexts"},{"type":"string","const":"chat_messages"},{"type":"string","const":"annotations"},{"type":"string","const":"evaluations"},{"type":"string","const":"image"},{"type":"string","const":"file"}]}},"required":["name","type"]},"default":[]}},"required":["name"]}}}},"security":[{"project_api_key":[]}]}},"/api/dataset/upload":{"post":{"operationId":"postApiDatasetUpload","description":"Create a new dataset from an uploaded file (CSV, JSON, JSONL)","responses":{},"security":[{"project_api_key":[]}]}},"/api/dataset/attachments":{"post":{"operationId":"postApiDatasetAttachments","description":"Upload a file for an image or file column and get the reference a cell holds. The project is named by the `projectId` query parameter; the file goes in the `file` multipart field, with an optional `datasetId` field.","parameters":[{"name":"projectId","in":"query","required":true,"description":"The project the file is stored for.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["file"],"properties":{"file":{"type":"string","format":"binary","description":"The file to store."},"datasetId":{"type":"string","description":"The dataset that owns the file. Omit it while the dataset is still a draft."}}}}}},"responses":{"200":{"description":"The reference the cell holds, and the file's metadata.","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":"The value to write into the cell, and the address the file is served from."},"name":{"type":"string","description":"The file name the reference carries."},"mediaType":{"type":"string","description":"The media type the file is stored under."},"sizeBytes":{"type":"number","description":"The size of the stored file, in bytes."}},"required":["url","name","mediaType","sizeBytes"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"413":{"description":"The file is larger than the upload limit.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"415":{"description":"The media type is not accepted.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Too many uploads for this project in one minute.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"security":[{"project_api_key":[]}]}},"/api/dataset/direct-upload":{"post":{"operationId":"postApiDatasetDirectUpload","description":"Start a direct browser→S3 dataset upload (returns a presigned PUT)","responses":{},"security":[{"project_api_key":[]}]}},"/api/dataset/direct-upload/staging/{uploadId}":{"put":{"operationId":"putApiDatasetDirectUploadStagingByUploadId","description":"Stream a heavy upload into staging when there is no browser-reachable S3","responses":{},"parameters":[{"schema":{"type":"string"},"in":"path","name":"uploadId","required":true}],"security":[{"project_api_key":[]}]}},"/api/dataset/direct-upload/{datasetId}/finalize":{"post":{"operationId":"postApiDatasetDirectUploadByDatasetIdFinalize","description":"Finalize a direct upload: size-check and start processing","responses":{},"parameters":[{"schema":{"type":"string"},"in":"path","name":"datasetId","required":true}],"security":[{"project_api_key":[]}]}},"/api/dataset/direct-upload/{datasetId}/retry":{"post":{"operationId":"postApiDatasetDirectUploadByDatasetIdRetry","description":"Retry normalization of a failed or stuck dataset","responses":{},"parameters":[{"schema":{"type":"string"},"in":"path","name":"datasetId","required":true}],"security":[{"project_api_key":[]}]}},"/api/dataset/direct-upload/{datasetId}":{"delete":{"operationId":"deleteApiDatasetDirectUploadByDatasetId","description":"Abort a still-pending direct upload and clean up its row","responses":{},"parameters":[{"schema":{"type":"string"},"in":"path","name":"datasetId","required":true}],"security":[{"project_api_key":[]}]}},"/api/dataset/{slugOrId}/upload":{"post":{"operationId":"postApiDatasetBySlugOrIdUpload","description":"Upload a file (CSV, JSON, JSONL) to an existing dataset","responses":{},"parameters":[{"schema":{"type":"string"},"in":"path","name":"slugOrId","required":true}],"security":[{"project_api_key":[]}]}},"/api/dataset/{slugOrId}/records":{"post":{"operationId":"postApiDatasetBySlugOrIdRecords","description":"Create records in a dataset in batch","responses":{},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"entries":{"type":"array","items":{"type":"object","additionalProperties":{}},"minItems":1,"maxItems":1000}},"required":["entries"]}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"slugOrId","required":true}],"security":[{"project_api_key":[]}]},"get":{"operationId":"getApiDatasetBySlugOrIdRecords","description":"List records for a dataset (paginated)","responses":{},"parameters":[{"in":"query","name":"page","schema":{"type":"integer","exclusiveMinimum":0,"default":1}},{"in":"query","name":"limit","schema":{"type":"integer","exclusiveMinimum":0,"maximum":1000,"default":50}},{"schema":{"type":"string"},"in":"path","name":"slugOrId","required":true}],"security":[{"project_api_key":[]}]},"delete":{"operationId":"deleteApiDatasetBySlugOrIdRecords","description":"Delete records from a dataset by IDs","responses":{},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"recordIds":{"type":"array","items":{"type":"string"},"minItems":1,"maxItems":1000}},"required":["recordIds"]}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"slugOrId","required":true}],"security":[{"project_api_key":[]}]}},"/api/dataset/{slug}/entries":{"post":{"operationId":"postApiDatasetBySlugEntries","description":"Add entries to a dataset","responses":{},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DatasetPostEntries"}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"security":[{"project_api_key":[]}]},"get":{"operationId":"getApiDatasetBySlugEntries","description":"List entries of a dataset (paginated). Same as GET /:slugOrId/records.","responses":{},"parameters":[{"in":"query","name":"page","schema":{"type":"integer","exclusiveMinimum":0,"default":1}},{"in":"query","name":"limit","schema":{"type":"integer","exclusiveMinimum":0,"maximum":1000,"default":50}},{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"security":[{"project_api_key":[]}]}},"/api/dataset/{slugOrId}":{"get":{"operationId":"getApiDatasetBySlugOrId","description":"Get a dataset by its slug or id.","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"datasetId":{"type":"string"},"projectId":{"type":"string"},"entry":{"type":"object","additionalProperties":{}},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","datasetId","projectId","entry","createdAt","updatedAt"]}}},"required":["data"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Dataset not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"slugOrId","required":true}],"security":[{"project_api_key":[]}]},"patch":{"operationId":"patchApiDatasetBySlugOrId","description":"Update a dataset by its slug or id","responses":{},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1},"columnTypes":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"type":{"anyOf":[{"type":"string","const":"string"},{"type":"string","const":"boolean"},{"type":"string","const":"number"},{"type":"string","const":"date"},{"type":"string","const":"list"},{"type":"string","const":"json"},{"type":"string","const":"spans"},{"type":"string","const":"rag_contexts"},{"type":"string","const":"chat_messages"},{"type":"string","const":"annotations"},{"type":"string","const":"evaluations"},{"type":"string","const":"image"},{"type":"string","const":"file"}]}},"required":["name","type"]}}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"slugOrId","required":true}],"security":[{"project_api_key":[]}]},"delete":{"operationId":"deleteApiDatasetBySlugOrId","description":"Archive a dataset (soft-delete)","responses":{},"parameters":[{"schema":{"type":"string"},"in":"path","name":"slugOrId","required":true}],"security":[{"project_api_key":[]}]}},"/api/dataset/{slugOrId}/records/{recordId}":{"patch":{"operationId":"patchApiDatasetBySlugOrIdRecordsByRecordId","description":"Update or create a record in a dataset","responses":{},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"entry":{"type":"object","additionalProperties":{}}},"required":["entry"]}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"slugOrId","required":true},{"schema":{"type":"string"},"in":"path","name":"recordId","required":true}],"security":[{"project_api_key":[]}]}},"/api/evaluators":{"get":{"operationId":"getApiEvaluators","description":"Get all evaluators for a project","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"projectId":{"type":"string"},"name":{"type":"string"},"slug":{"type":["string","null"]},"type":{"type":"string"},"config":{"type":["object","null"],"additionalProperties":{}},"workflowId":{"type":["string","null"]},"copiedFromEvaluatorId":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"fields":{"type":"array","items":{"type":"object","properties":{"identifier":{"type":"string"},"type":{"type":"string"},"optional":{"type":"boolean"}},"required":["identifier","type"]}},"outputFields":{"type":"array","items":{"type":"object","properties":{"identifier":{"type":"string"},"type":{"type":"string"},"optional":{"type":"boolean"}},"required":["identifier","type"]}},"workflowName":{"type":"string"},"workflowIcon":{"type":"string"},"platformUrl":{"type":"string","format":"uri"}},"required":["id","projectId","name","slug","type","config","workflowId","copiedFromEvaluatorId","createdAt","updatedAt","fields","outputFields","platformUrl"]}}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"security":[{"project_api_key":[]}]},"post":{"operationId":"postApiEvaluators","description":"Create a new evaluator","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"projectId":{"type":"string"},"name":{"type":"string"},"slug":{"type":["string","null"]},"type":{"type":"string"},"config":{"type":["object","null"],"additionalProperties":{}},"workflowId":{"type":["string","null"]},"copiedFromEvaluatorId":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"fields":{"type":"array","items":{"type":"object","properties":{"identifier":{"type":"string"},"type":{"type":"string"},"optional":{"type":"boolean"}},"required":["identifier","type"]}},"outputFields":{"type":"array","items":{"type":"object","properties":{"identifier":{"type":"string"},"type":{"type":"string"},"optional":{"type":"boolean"}},"required":["identifier","type"]}},"workflowName":{"type":"string"},"workflowIcon":{"type":"string"},"platformUrl":{"type":"string","format":"uri"}},"required":["id","projectId","name","slug","type","config","workflowId","copiedFromEvaluatorId","createdAt","updatedAt","fields","outputFields","platformUrl"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"config":{"type":"object","additionalProperties":{}}},"required":["name","config"]}}}},"security":[{"project_api_key":[]}]}},"/api/evaluators/{idOrSlug}":{"get":{"operationId":"getApiEvaluatorsByIdOrSlug","description":"Get a specific evaluator by ID or slug","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"projectId":{"type":"string"},"name":{"type":"string"},"slug":{"type":["string","null"]},"type":{"type":"string"},"config":{"type":["object","null"],"additionalProperties":{}},"workflowId":{"type":["string","null"]},"copiedFromEvaluatorId":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"fields":{"type":"array","items":{"type":"object","properties":{"identifier":{"type":"string"},"type":{"type":"string"},"optional":{"type":"boolean"}},"required":["identifier","type"]}},"outputFields":{"type":"array","items":{"type":"object","properties":{"identifier":{"type":"string"},"type":{"type":"string"},"optional":{"type":"boolean"}},"required":["identifier","type"]}},"workflowName":{"type":"string"},"workflowIcon":{"type":"string"},"platformUrl":{"type":"string","format":"uri"}},"required":["id","projectId","name","slug","type","config","workflowId","copiedFromEvaluatorId","createdAt","updatedAt","fields","outputFields","platformUrl"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Evaluator not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"idOrSlug","required":true}],"security":[{"project_api_key":[]}]}},"/api/evaluators/{id}":{"put":{"operationId":"putApiEvaluatorsById","description":"Update an existing evaluator","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"projectId":{"type":"string"},"name":{"type":"string"},"slug":{"type":["string","null"]},"type":{"type":"string"},"config":{"type":["object","null"],"additionalProperties":{}},"workflowId":{"type":["string","null"]},"copiedFromEvaluatorId":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"fields":{"type":"array","items":{"type":"object","properties":{"identifier":{"type":"string"},"type":{"type":"string"},"optional":{"type":"boolean"}},"required":["identifier","type"]}},"outputFields":{"type":"array","items":{"type":"object","properties":{"identifier":{"type":"string"},"type":{"type":"string"},"optional":{"type":"boolean"}},"required":["identifier","type"]}},"workflowName":{"type":"string"},"workflowIcon":{"type":"string"},"platformUrl":{"type":"string","format":"uri"}},"required":["id","projectId","name","slug","type","config","workflowId","copiedFromEvaluatorId","createdAt","updatedAt","fields","outputFields","platformUrl"]}}}},"400":{"description":"Bad request (e.g. attempting to change evaluatorType)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Evaluator not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"config":{"type":"object","additionalProperties":{}}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]},"delete":{"operationId":"deleteApiEvaluatorsById","description":"Archive (soft-delete) an evaluator","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Evaluator not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]}},"/api/events/track":{"post":{"operationId":"postApiEventsTrack","description":"Record a user event (e.g. thumbs up/down, selected text) attached to a trace. Predefined event types validate against their schemas; custom event types pass through `trackEventRESTParamsValidatorSchema`.","responses":{"200":{"description":"Event tracked","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","const":"Event tracked"}},"required":["message"]}}}},"400":{"description":"Invalid event payload","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"security":[{"project_api_key":[]}]}},"/api/experiments":{"get":{"operationId":"getApiExperiments","summary":"List experiments for the project","description":"List experiments for the project. Includes a runs count and last-run timestamp per experiment.","tags":["Experiments"],"parameters":[{"in":"query","name":"page","required":false,"schema":{"type":"integer","default":1},"description":"1-based page number"},{"in":"query","name":"pageSize","required":false,"schema":{"type":"integer","default":50,"maximum":200},"description":"Experiments per page, capped at 200"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"experiments":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":["string","null"]},"type":{"type":"string"},"workflowId":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"runsCount":{"type":"number"},"lastRunAt":{"type":["string","null"]}},"required":["id","slug","name","type","workflowId","createdAt","updatedAt","runsCount","lastRunAt"]}},"pagination":{"type":"object","properties":{"page":{"type":"number"},"pageSize":{"type":"number"},"totalHits":{"type":"number"},"hasMore":{"type":"boolean"}},"required":["page","pageSize","totalHits","hasMore"]}},"required":["experiments","pagination"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"security":[{"project_api_key":[]}]},"post":{"operationId":"postApiExperiments","summary":"Create an experiment and its setup","description":"Create an evaluations experiment. Send a setup to start from, or send none and get a blank workbench with one inline dataset. The slug it answers with is what every other experiment endpoint takes.","tags":["Experiments"],"responses":{"200":{"description":"Experiment created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of the created experiment"},"slug":{"type":"string","description":"Slug to address the experiment by"},"version":{"type":"number","description":"Version of the saved setup, starting at 1"}},"required":["id","slug","version"]}}}},"400":{"description":"The setup did not match the schema (experiment_invalid_workbench_state) or points at something that no longer exists (experiment_workbench_missing_reference)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable failure code; branch on this"},"message":{"type":"string"},"fault":{"type":"string","description":"Who the failure is attributable to: customer, platform, provider"},"tips":{"type":"array","items":{"type":"string"}},"docsUrl":{"type":"string"}},"required":["error"],"additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"description":"Name for the experiment. A draft name is picked when omitted."},"state":{"type":"object","additionalProperties":{},"description":"Setup to start from. Omit for a blank workbench with one inline dataset."}}}}}},"security":[{"project_api_key":[]}]}},"/api/experiments/{slug}":{"get":{"operationId":"getApiExperimentsBySlug","summary":"Read one experiment","description":"Read a single experiment by its slug, in the same shape the list returns. Accepts the experiment id as well, so either identifier the list hands back can be used.","tags":["Experiments"],"parameters":[{"in":"path","name":"slug","required":true,"schema":{"type":"string"},"description":"The experiment's slug, or its id"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":["string","null"]},"type":{"type":"string"},"workflowId":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"runsCount":{"type":"number"},"lastRunAt":{"type":["string","null"]}},"required":["id","slug","name","type","workflowId","createdAt","updatedAt","runsCount","lastRunAt"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"No experiment with that slug or id in this project","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable failure code; branch on this"},"message":{"type":"string"},"fault":{"type":"string","description":"Who the failure is attributable to: customer, platform, provider"},"tips":{"type":"array","items":{"type":"string"}},"docsUrl":{"type":"string"}},"required":["error"],"additionalProperties":true}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"security":[{"project_api_key":[]}]}},"/api/evaluations/list":{"get":{"operationId":"getApiEvaluationsList","summary":"List the built-in evaluators","description":"List every evaluator this server ships with, along with the `data` fields each one needs and the settings it accepts. The keys of `evaluators` are the ids you put in the evaluate path. The list is the same for every caller and needs no credential.","tags":["Evaluations"],"security":[],"responses":{"200":{"description":"The evaluator catalogue","content":{"application/json":{"schema":{"type":"object","properties":{"evaluators":{"type":"object","additionalProperties":{"type":"object","properties":{"name":{"type":"string","description":"Display name of the evaluator"},"description":{"type":"string"},"category":{"type":"string"},"docsUrl":{"type":"string"},"isGuardrail":{"type":"boolean","description":"Whether this evaluator can gate a request as a guardrail"},"requiredFields":{"type":"array","items":{"type":"string"},"description":"`data` keys the evaluate call must supply"},"optionalFields":{"type":"array","items":{"type":"string"}},"settings":{"type":"object","additionalProperties":{},"description":"Each setting's default and description"},"settings_json_schema":{"type":"object","additionalProperties":{},"description":"JSON Schema for this evaluator's settings object"},"envVars":{"type":"array","items":{"type":"string"},"description":"Server-side variables the evaluator needs configured"},"result":{"type":"object","additionalProperties":{},"description":"What its score, passed and label mean"}},"required":["name","description","category","isGuardrail","requiredFields","optionalFields","settings","settings_json_schema","envVars","result"]},"description":"Keyed by evaluator id, the value you put in the evaluate path"}},"required":["evaluators"]}}}}}}},"/api/evaluations/batch/log_results":{"post":{"operationId":"postApiEvaluationsBatchLogResults","summary":"Report batch evaluation results","description":"Report the rows of a batch evaluation against an experiment, so its scores and progress show up in the app. This is the second half of an SDK batch evaluation: create the experiment with `POST /api/experiment/init`, then post rows here as they finish. Identify the experiment by either `experiment_id` or `experiment_slug`. Bodies up to 20MB are accepted.","tags":["Evaluations"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"type":"object","properties":{"run_id":{"type":"string"},"workflow_version_id":{"type":"string","nullable":true},"progress":{"type":"number","nullable":true},"total":{"type":"number","nullable":true},"dataset":{"type":"array","items":{"type":"object","properties":{"index":{"type":"number"},"target_id":{"type":"string","nullable":true},"entry":{"type":"object","additionalProperties":{}},"predicted":{"type":"object","additionalProperties":{}},"cost":{"type":"number","nullable":true},"duration":{"type":"number","nullable":true},"error":{"type":"string","nullable":true},"trace_id":{"type":"string","nullable":true}},"required":["index","entry"],"additionalProperties":false}},"evaluations":{"type":"array","items":{"type":"object","properties":{"evaluator":{"type":"string"},"name":{"type":"string","nullable":true},"target_id":{"type":"string","nullable":true},"status":{"anyOf":[{"type":"string","enum":["processed"]},{"type":"string","enum":["skipped"]},{"type":"string","enum":["error"]}]},"index":{"type":"number"},"duration":{"type":"number","nullable":true},"inputs":{"type":"object","additionalProperties":{}},"score":{"type":"number","nullable":true},"label":{"type":"string","nullable":true},"passed":{"type":"boolean","nullable":true},"details":{"type":"string","nullable":true},"cost":{"type":"number","nullable":true}},"required":["evaluator","status","index"],"additionalProperties":false}}}},{"type":"object","properties":{"experiment_id":{"type":"string","nullable":true},"experiment_slug":{"type":"string","nullable":true},"run_id":{"type":"string","nullable":true},"workflow_id":{"type":"string","nullable":true},"name":{"type":"string","nullable":true},"targets":{"type":"array","items":{"allOf":[{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"prompt_id":{"type":"string","nullable":true},"prompt_version":{"type":"number","nullable":true},"agent_id":{"type":"string","nullable":true},"evaluator_id":{"type":"string","nullable":true},"model":{"type":"string","nullable":true},"metadata":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"}]},"nullable":true}},"required":["id","name"]},{"type":"object","properties":{"type":{"anyOf":[{"type":"string","enum":["prompt"]},{"type":"string","enum":["agent"]},{"type":"string","enum":["evaluator"]},{"type":"string","enum":["workflow"]},{"type":"string","enum":["custom"]}]}}}]},"nullable":true},"timestamps":{"type":"object","properties":{"created_at":{"type":"number","nullable":true},"finished_at":{"type":"number","nullable":true},"stopped_at":{"type":"number","nullable":true}},"additionalProperties":false}},"required":["run_id"]}]}}}},"responses":{"200":{"description":"The rows were recorded","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable confirmation"}},"required":["message"]}}}},"400":{"description":"The request was not sent as application/json, failed validation, named neither experiment_id nor experiment_slug, or carried timestamps in seconds rather than milliseconds","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Set when the request was rejected before validation"},"error":{"type":"string","description":"Set when the body parsed and then failed validation"}}}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"The failure, as a sentence"},"kind":{"type":"string","description":"Stable failure code, on the failures that carry one"},"meta":{"type":"object","additionalProperties":{},"description":"What the code needs to be acted on, such as the missing field"}},"required":["error"]}}}},"403":{"description":"The API key lacks evaluations:manage","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"The failure, as a sentence"},"kind":{"type":"string","description":"Stable failure code, on the failures that carry one"},"meta":{"type":"object","additionalProperties":{},"description":"What the code needs to be acted on, such as the missing field"}},"required":["error"]}}}}},"security":[{"project_api_key":[]}]}},"/api/evaluations/{evaluator}/evaluate":{"post":{"operationId":"postApiEvaluationsByEvaluatorEvaluate","summary":"Run an evaluator","description":"Run one evaluator over a single input and get its score back. Built-in evaluators whose id has two segments, such as `ragas/faithfulness`, are addressed with the two-segment form of this path. Bodies up to 30MB are accepted.","tags":["Evaluations"],"parameters":[{"in":"path","name":"evaluator","required":true,"schema":{"type":"string"},"description":"Which evaluator to run. Either a built-in id (`ragas/faithfulness`), the slug of a monitor configured in this project, or `evaluators/{slug|id}` for a saved evaluator. `GET /api/evaluations/list` returns the built-in ids."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":{},"description":"What the evaluator scores. Which fields are required depends on the evaluator; its own entry under Built-in Evaluators lists them."},"settings":{"type":"object","additionalProperties":{},"description":"Per-call overrides of the evaluator's settings. Anything omitted falls back to the saved evaluator or monitor, then to the evaluator's own defaults."},"trace_id":{"type":"string","nullable":true,"description":"Attaches the result to a trace you already sent"},"evaluation_id":{"type":"string","nullable":true,"description":"Supply your own id to make the call idempotent"},"evaluator_id":{"type":"string","nullable":true},"name":{"type":"string","nullable":true,"description":"Overrides the name the result is recorded under"},"as_guardrail":{"type":"boolean","nullable":true,"description":"Evaluate as a guardrail: a skipped or failed evaluation answers `passed` rather than an error, so a caller can gate on one field. The /api/guardrails path sets this for you."}},"required":["data"],"additionalProperties":false}}}},"responses":{"200":{"description":"The evaluator ran, declined, or failed. Branch on `status`; in guardrail mode `passed` is set on all three.","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"status":{"type":"string","const":"processed"},"score":{"type":"number"},"passed":{"type":"boolean"},"label":{"type":"string"},"details":{"type":"string"},"cost":{"type":"object","properties":{"currency":{"type":"string"},"amount":{"type":"number"}},"required":["currency","amount"],"description":"What running the evaluator cost"},"raw_response":{"description":"The evaluator's own output, unprocessed"}},"required":["status"]},{"type":"object","properties":{"status":{"type":"string","const":"skipped"},"details":{"type":"string","description":"Why the evaluator declined to score this input"},"cost":{"type":"object","properties":{"currency":{"type":"string"},"amount":{"type":"number"}},"required":["currency","amount"],"description":"What the attempt cost, when the evaluator spent money before declining to score"},"passed":{"type":"boolean","description":"Always true in guardrail mode, so a skip does not block"}},"required":["status"]},{"type":"object","properties":{"status":{"type":"string","const":"error"},"error_type":{"type":"string","const":"EVALUATOR_ERROR","description":"Constant: the evaluator's own type is not exposed"},"details":{"type":"string"},"passed":{"type":"boolean","description":"Always true in guardrail mode, so a failure does not block"}},"required":["status","error_type","details"]}]}}}},"400":{"description":"The body was not valid JSON, failed validation, or omitted a field this evaluator requires","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"The failure, as a sentence"},"kind":{"type":"string","description":"Stable failure code, on the failures that carry one"},"meta":{"type":"object","additionalProperties":{},"description":"What the code needs to be acted on, such as the missing field"}},"required":["error"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"The failure, as a sentence"},"kind":{"type":"string","description":"Stable failure code, on the failures that carry one"},"meta":{"type":"object","additionalProperties":{},"description":"What the code needs to be acted on, such as the missing field"}},"required":["error"]}}}},"403":{"description":"The API key lacks evaluations:manage","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"The failure, as a sentence"},"kind":{"type":"string","description":"Stable failure code, on the failures that carry one"},"meta":{"type":"object","additionalProperties":{},"description":"What the code needs to be acted on, such as the missing field"}},"required":["error"]}}}},"404":{"description":"No evaluator answers to that id","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"The failure, as a sentence"},"kind":{"type":"string","description":"Stable failure code, on the failures that carry one"},"meta":{"type":"object","additionalProperties":{},"description":"What the code needs to be acted on, such as the missing field"}},"required":["error"]}}}}},"security":[{"project_api_key":[]}]}},"/api/evaluations/{evaluator}/{subpath}/evaluate":{"post":{"operationId":"postApiEvaluationsByEvaluatorBySubpathEvaluate","summary":"Run a namespaced evaluator","description":"Run one evaluator whose id has two segments, such as `ragas/faithfulness` or `langevals/valid_format`. Identical to the single-segment form in every other respect; the id is simply split across two path segments.","tags":["Evaluations"],"parameters":[{"in":"path","name":"evaluator","required":true,"schema":{"type":"string"},"description":"First segment of the evaluator id, such as `ragas`"},{"in":"path","name":"subpath","required":true,"schema":{"type":"string"},"description":"Second segment of the evaluator id, such as `faithfulness`"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":{},"description":"What the evaluator scores. Which fields are required depends on the evaluator; its own entry under Built-in Evaluators lists them."},"settings":{"type":"object","additionalProperties":{},"description":"Per-call overrides of the evaluator's settings. Anything omitted falls back to the saved evaluator or monitor, then to the evaluator's own defaults."},"trace_id":{"type":"string","nullable":true,"description":"Attaches the result to a trace you already sent"},"evaluation_id":{"type":"string","nullable":true,"description":"Supply your own id to make the call idempotent"},"evaluator_id":{"type":"string","nullable":true},"name":{"type":"string","nullable":true,"description":"Overrides the name the result is recorded under"},"as_guardrail":{"type":"boolean","nullable":true,"description":"Evaluate as a guardrail: a skipped or failed evaluation answers `passed` rather than an error, so a caller can gate on one field. The /api/guardrails path sets this for you."}},"required":["data"],"additionalProperties":false}}}},"responses":{"200":{"description":"The evaluator ran, declined, or failed. Branch on `status`; in guardrail mode `passed` is set on all three.","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"status":{"type":"string","const":"processed"},"score":{"type":"number"},"passed":{"type":"boolean"},"label":{"type":"string"},"details":{"type":"string"},"cost":{"type":"object","properties":{"currency":{"type":"string"},"amount":{"type":"number"}},"required":["currency","amount"],"description":"What running the evaluator cost"},"raw_response":{"description":"The evaluator's own output, unprocessed"}},"required":["status"]},{"type":"object","properties":{"status":{"type":"string","const":"skipped"},"details":{"type":"string","description":"Why the evaluator declined to score this input"},"cost":{"type":"object","properties":{"currency":{"type":"string"},"amount":{"type":"number"}},"required":["currency","amount"],"description":"What the attempt cost, when the evaluator spent money before declining to score"},"passed":{"type":"boolean","description":"Always true in guardrail mode, so a skip does not block"}},"required":["status"]},{"type":"object","properties":{"status":{"type":"string","const":"error"},"error_type":{"type":"string","const":"EVALUATOR_ERROR","description":"Constant: the evaluator's own type is not exposed"},"details":{"type":"string"},"passed":{"type":"boolean","description":"Always true in guardrail mode, so a failure does not block"}},"required":["status","error_type","details"]}]}}}},"400":{"description":"The body was not valid JSON, failed validation, or omitted a field this evaluator requires","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"The failure, as a sentence"},"kind":{"type":"string","description":"Stable failure code, on the failures that carry one"},"meta":{"type":"object","additionalProperties":{},"description":"What the code needs to be acted on, such as the missing field"}},"required":["error"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"The failure, as a sentence"},"kind":{"type":"string","description":"Stable failure code, on the failures that carry one"},"meta":{"type":"object","additionalProperties":{},"description":"What the code needs to be acted on, such as the missing field"}},"required":["error"]}}}},"403":{"description":"The API key lacks evaluations:manage","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"The failure, as a sentence"},"kind":{"type":"string","description":"Stable failure code, on the failures that carry one"},"meta":{"type":"object","additionalProperties":{},"description":"What the code needs to be acted on, such as the missing field"}},"required":["error"]}}}},"404":{"description":"No evaluator answers to that id","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"The failure, as a sentence"},"kind":{"type":"string","description":"Stable failure code, on the failures that carry one"},"meta":{"type":"object","additionalProperties":{},"description":"What the code needs to be acted on, such as the missing field"}},"required":["error"]}}}}},"security":[{"project_api_key":[]}]}},"/api/guardrails/{evaluator}/evaluate":{"post":{"operationId":"postApiGuardrailsByEvaluatorEvaluate","summary":"Run an evaluator as a guardrail","description":"Run an evaluator inline and gate on one boolean. Same call as the evaluate path with `as_guardrail` set: every outcome carries `passed`, so an evaluator that skips or fails does not block the request it was guarding. Check `passed` and let the request through when it is true.","tags":["Evaluations"],"parameters":[{"in":"path","name":"evaluator","required":true,"schema":{"type":"string"},"description":"Which evaluator to run. Either a built-in id (`ragas/faithfulness`), the slug of a monitor configured in this project, or `evaluators/{slug|id}` for a saved evaluator. `GET /api/evaluations/list` returns the built-in ids."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":{},"description":"What the evaluator scores. Which fields are required depends on the evaluator; its own entry under Built-in Evaluators lists them."},"settings":{"type":"object","additionalProperties":{},"description":"Per-call overrides of the evaluator's settings. Anything omitted falls back to the saved evaluator or monitor, then to the evaluator's own defaults."},"trace_id":{"type":"string","nullable":true,"description":"Attaches the result to a trace you already sent"},"evaluation_id":{"type":"string","nullable":true,"description":"Supply your own id to make the call idempotent"},"evaluator_id":{"type":"string","nullable":true},"name":{"type":"string","nullable":true,"description":"Overrides the name the result is recorded under"},"as_guardrail":{"type":"boolean","nullable":true,"description":"Evaluate as a guardrail: a skipped or failed evaluation answers `passed` rather than an error, so a caller can gate on one field. The /api/guardrails path sets this for you."}},"required":["data"],"additionalProperties":false}}}},"responses":{"200":{"description":"The evaluator ran, declined, or failed. Branch on `status`; in guardrail mode `passed` is set on all three.","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"status":{"type":"string","const":"processed"},"score":{"type":"number"},"passed":{"type":"boolean"},"label":{"type":"string"},"details":{"type":"string"},"cost":{"type":"object","properties":{"currency":{"type":"string"},"amount":{"type":"number"}},"required":["currency","amount"],"description":"What running the evaluator cost"},"raw_response":{"description":"The evaluator's own output, unprocessed"}},"required":["status"]},{"type":"object","properties":{"status":{"type":"string","const":"skipped"},"details":{"type":"string","description":"Why the evaluator declined to score this input"},"cost":{"type":"object","properties":{"currency":{"type":"string"},"amount":{"type":"number"}},"required":["currency","amount"],"description":"What the attempt cost, when the evaluator spent money before declining to score"},"passed":{"type":"boolean","description":"Always true in guardrail mode, so a skip does not block"}},"required":["status"]},{"type":"object","properties":{"status":{"type":"string","const":"error"},"error_type":{"type":"string","const":"EVALUATOR_ERROR","description":"Constant: the evaluator's own type is not exposed"},"details":{"type":"string"},"passed":{"type":"boolean","description":"Always true in guardrail mode, so a failure does not block"}},"required":["status","error_type","details"]}]}}}},"400":{"description":"The body was not valid JSON, failed validation, or omitted a field this evaluator requires","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"The failure, as a sentence"},"kind":{"type":"string","description":"Stable failure code, on the failures that carry one"},"meta":{"type":"object","additionalProperties":{},"description":"What the code needs to be acted on, such as the missing field"}},"required":["error"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"The failure, as a sentence"},"kind":{"type":"string","description":"Stable failure code, on the failures that carry one"},"meta":{"type":"object","additionalProperties":{},"description":"What the code needs to be acted on, such as the missing field"}},"required":["error"]}}}},"403":{"description":"The API key lacks evaluations:manage","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"The failure, as a sentence"},"kind":{"type":"string","description":"Stable failure code, on the failures that carry one"},"meta":{"type":"object","additionalProperties":{},"description":"What the code needs to be acted on, such as the missing field"}},"required":["error"]}}}},"404":{"description":"No evaluator answers to that id","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"The failure, as a sentence"},"kind":{"type":"string","description":"Stable failure code, on the failures that carry one"},"meta":{"type":"object","additionalProperties":{},"description":"What the code needs to be acted on, such as the missing field"}},"required":["error"]}}}}},"security":[{"project_api_key":[]}]}},"/api/dataset/evaluate":{"post":{"operationId":"postApiDatasetEvaluate","summary":"Evaluate a dataset","description":"Run one evaluator across a saved dataset and record the result against an experiment. Name the dataset by slug and the evaluator the same way the evaluate endpoints do; results are grouped under `experimentSlug`, or under a generated batch id when you omit it. Bodies up to 30MB are accepted.","tags":["Datasets"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"evaluation":{"type":"string","description":"Which evaluator to run, addressed the same way the evaluate endpoints address it"},"datasetSlug":{"type":"string","description":"The saved dataset to evaluate"},"experimentSlug":{"type":"string","description":"Groups the results under an experiment. Omit it and a batch id is generated instead."},"batchId":{"type":"string","description":"Older name for experimentSlug, used when that is absent"},"data":{"type":"object","additionalProperties":{},"nullable":true,"description":"Extra fields merged into every row before evaluating"},"settings":{"type":"object","additionalProperties":{},"nullable":true,"description":"Per-call overrides of the evaluator's settings"}},"required":["evaluation","datasetSlug"],"additionalProperties":false}}}},"responses":{"200":{"description":"The evaluator ran; branch on `status`","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"status":{"type":"string","const":"processed"},"score":{"type":"number"},"passed":{"type":"boolean"},"label":{"type":"string"},"details":{"type":"string"},"cost":{"type":"object","properties":{"currency":{"type":"string"},"amount":{"type":"number"}},"required":["currency","amount"],"description":"What running the evaluator cost"},"raw_response":{"description":"The evaluator's own output, unprocessed"}},"required":["status"]},{"type":"object","properties":{"status":{"type":"string","const":"skipped"},"details":{"type":"string","description":"Why the evaluator declined to score this input"},"cost":{"type":"object","properties":{"currency":{"type":"string"},"amount":{"type":"number"}},"required":["currency","amount"],"description":"What the attempt cost, when the evaluator spent money before declining to score"},"passed":{"type":"boolean","description":"Always true in guardrail mode, so a skip does not block"}},"required":["status"]},{"type":"object","properties":{"status":{"type":"string","const":"error"},"error_type":{"type":"string","const":"EVALUATOR_ERROR","description":"Constant: the evaluator's own type is not exposed"},"details":{"type":"string"},"passed":{"type":"boolean","description":"Always true in guardrail mode, so a failure does not block"}},"required":["status","error_type","details"]}]}}}},"400":{"description":"The body was not valid JSON, failed validation, or named an evaluator that does not exist","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Set when the request was rejected before validation"},"error":{"type":"string","description":"Set when the body parsed and then failed validation"}}}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Set when the request was rejected before validation"},"error":{"type":"string","description":"Set when the body parsed and then failed validation"}}}}}},"403":{"description":"The API key lacks evaluations:manage","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"The failure, as a sentence"},"kind":{"type":"string","description":"Stable failure code, on the failures that carry one"},"meta":{"type":"object","additionalProperties":{},"description":"What the code needs to be acted on, such as the missing field"}},"required":["error"]}}}},"404":{"description":"No dataset with that slug","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"The failure, as a sentence"},"kind":{"type":"string","description":"Stable failure code, on the failures that carry one"},"meta":{"type":"object","additionalProperties":{},"description":"What the code needs to be acted on, such as the missing field"}},"required":["error"]}}}},"413":{"description":"The body is larger than 30MB. Refused before it is read, so the response is the plain sentence `Payload Too Large` rather than a JSON error","content":{"text/plain":{"schema":{"type":"string"}}}}},"security":[{"project_api_key":[]}]}},"/api/experiments/{slug}/run":{"post":{"operationId":"postApiExperimentsBySlugRun","summary":"Run an experiment","description":"Start a run of a saved experiment, addressed by slug. Returns a runId to poll straight away. Send `Accept: text/event-stream` instead to stream progress events until the run finishes.","tags":["Experiments"],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"Rows to evaluate inline, instead of the experiment's saved dataset. Mutually exclusive with dataset_id."},"dataset_id":{"type":"string","description":"A saved dataset to evaluate, instead of the one the experiment is configured with. Mutually exclusive with data."},"parameters":{"type":"object","additionalProperties":{"oneOf":[{"type":"string"},{"type":"number"},{"type":"boolean"}]},"description":"Constant inputs applied to every row, overriding fields of the same name"},"row_indices":{"type":"array","items":{"type":"integer","minimum":0},"description":"Run only these rows of the dataset, by zero-based index"}},"not":{"required":["data","dataset_id"]}}}}},"responses":{"200":{"description":"Run started","content":{"application/json":{"schema":{"type":"object","properties":{"runId":{"type":"string","description":"Identifier to poll this run with"},"status":{"type":"string","const":"running"},"total":{"type":"number","description":"Number of cells this run will execute"},"runUrl":{"type":"string","description":"Link to the run in the LangWatch app"}},"required":["runId","status","total"]}},"text/event-stream":{"schema":{"type":"string","description":"Progress events, ending with a done event carrying the summary"}}}},"400":{"description":"The body was not valid JSON, failed input validation, or the experiment has no dataset configured","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Missing or invalid API key, or the key lacks the permission","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable failure code; branch on this"},"message":{"type":"string"},"fault":{"type":"string","description":"Who the failure is attributable to: customer, platform, provider"},"tips":{"type":"array","items":{"type":"string"}},"docsUrl":{"type":"string"}},"required":["error"],"additionalProperties":true}}}},"404":{"description":"No such experiment or run in this project","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable failure code; branch on this"},"message":{"type":"string"},"fault":{"type":"string","description":"Who the failure is attributable to: customer, platform, provider"},"tips":{"type":"array","items":{"type":"string"}},"docsUrl":{"type":"string"}},"required":["error"],"additionalProperties":true}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"security":[{"project_api_key":[]}]}},"/api/experiments/runs":{"get":{"operationId":"getApiExperimentsRuns","summary":"List runs of an experiment","description":"Runs recorded for one experiment, newest first. Page through them with `page` and `pageSize`.","tags":["Experiments"],"parameters":[{"in":"query","name":"experimentSlug","required":true,"schema":{"type":"string"},"description":"Slug of the experiment whose runs you want"},{"in":"query","name":"page","required":false,"schema":{"type":"integer","default":1},"description":"1-based page number"},{"in":"query","name":"pageSize","required":false,"schema":{"type":"integer","default":50,"maximum":200},"description":"Runs per page, capped at 200"}],"responses":{"200":{"description":"Runs for the experiment","content":{"application/json":{"schema":{"type":"object","properties":{"experimentId":{"type":"string"},"experimentSlug":{"type":"string"},"runs":{"type":"array","items":{"type":"object","properties":{"experimentId":{"type":"string"},"runId":{"type":"string"},"workflowVersion":{"type":["object","null"],"properties":{"id":{"type":"string"},"version":{"type":"string"},"commitMessage":{"type":"string"},"author":{"type":["object","null"],"properties":{"name":{"type":["string","null"]},"image":{"type":["string","null"]}},"required":["name","image"]}},"required":["id","version","commitMessage","author"]},"timestamps":{"type":"object","properties":{"createdAt":{"type":"number"},"updatedAt":{"type":"number"},"finishedAt":{"type":["number","null"]},"stoppedAt":{"type":["number","null"]}},"required":["createdAt","updatedAt"]},"progress":{"type":["number","null"]},"total":{"type":["number","null"]},"summary":{"type":"object","properties":{"datasetCost":{"type":"number"},"evaluationsCost":{"type":"number"},"datasetAverageCost":{"type":"number"},"datasetAverageDuration":{"type":"number"},"evaluationsAverageCost":{"type":"number"},"evaluationsAverageDuration":{"type":"number"},"evaluations":{"type":"object","additionalProperties":{"type":"object","properties":{"name":{"type":"string"},"averageScore":{"type":["number","null"]},"averagePassed":{"type":"number"}},"required":["name","averageScore"]}}},"required":["evaluations"]}},"required":["experimentId","runId","workflowVersion","timestamps","summary"]}},"pagination":{"type":"object","properties":{"page":{"type":"number"},"pageSize":{"type":"number"},"totalHits":{"type":"number"},"hasMore":{"type":"boolean"}},"required":["page","pageSize","totalHits","hasMore"]}},"required":["experimentId","experimentSlug","runs","pagination"]}}}},"400":{"description":"experimentSlug was not supplied","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Missing or invalid API key, or the key lacks the permission","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable failure code; branch on this"},"message":{"type":"string"},"fault":{"type":"string","description":"Who the failure is attributable to: customer, platform, provider"},"tips":{"type":"array","items":{"type":"string"}},"docsUrl":{"type":"string"}},"required":["error"],"additionalProperties":true}}}},"404":{"description":"No such experiment or run in this project","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable failure code; branch on this"},"message":{"type":"string"},"fault":{"type":"string","description":"Who the failure is attributable to: customer, platform, provider"},"tips":{"type":"array","items":{"type":"string"}},"docsUrl":{"type":"string"}},"required":["error"],"additionalProperties":true}}}}},"security":[{"project_api_key":[]}]}},"/api/experiments/runs/{runId}":{"get":{"operationId":"getApiExperimentsRunsByRunId","summary":"Poll a run","description":"Current state of one run. Returns progress while it is going and a summary once it finishes, so a CI job can poll this until `status` leaves `running`.","tags":["Experiments"],"responses":{"200":{"description":"Run state","content":{"application/json":{"schema":{"type":"object","properties":{"runId":{"type":"string"},"status":{"type":"string","enum":["pending","running","completed","failed","stopped"]},"progress":{"type":"number","description":"Cells finished so far"},"total":{"type":"number","description":"Cells in the run"},"startedAt":{"type":"number","description":"Unix milliseconds"},"finishedAt":{"type":"number","description":"Unix milliseconds; set once the run is no longer running"},"summary":{"type":"object","properties":{"runId":{"type":"string"},"totalCells":{"type":"number","description":"Cells the run set out to execute"},"completedCells":{"type":"number"},"failedCells":{"type":"number"},"duration":{"type":"number","description":"Wall-clock milliseconds"},"chDispatchFailures":{"type":"number","description":"Non-zero means some rows may be missing from the stored results"},"timestamps":{"type":"object","properties":{"startedAt":{"type":"number"},"finishedAt":{"type":"number"},"stoppedAt":{"type":"number"}},"required":["startedAt"]},"targets":{"type":"array","items":{"type":"object","properties":{"targetId":{"type":"string"},"name":{"type":"string"},"passed":{"type":"number"},"failed":{"type":"number"},"avgLatency":{"type":"number"},"totalCost":{"type":"number"}},"required":["targetId","name","passed","failed","avgLatency","totalCost"]}},"evaluators":{"type":"array","items":{"type":"object","properties":{"evaluatorId":{"type":"string"},"name":{"type":"string"},"passed":{"type":"number"},"failed":{"type":"number"},"passRate":{"type":"number"},"avgScore":{"type":"number"}},"required":["evaluatorId","name","passed","failed","passRate"]}},"totalPassed":{"type":"number"},"totalFailed":{"type":"number"},"passRate":{"type":"number"},"totalCost":{"type":"number"},"runUrl":{"type":"string","description":"Link to the run in the LangWatch app"}},"required":["runId","totalCells","completedCells","failedCells","duration","timestamps"],"description":"Present when completed"},"error":{"type":"string","description":"Stable failure code, present when failed. Not display copy: render your own wording keyed on it."},"domainError":{"type":"object","properties":{"code":{"type":"string","description":"Stable failure code; branch on this"},"kind":{"type":"string","description":"Deprecated alias of code, for older clients"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"httpStatus":{"type":"number"},"fault":{"type":"string","description":"Who the failure is attributable to: customer, platform, provider"},"traceId":{"type":"string"},"tips":{"type":"array","items":{"type":"string"}},"docsUrl":{"type":"string"}},"required":["code","kind"],"description":"The full failure envelope, when the failure carried one"},"traceId":{"type":"string","description":"Trace id for failures that carry no code, to quote in support"}},"required":["runId","status","progress","total"]}}}},"401":{"description":"Missing or invalid API key, or the key lacks the permission","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable failure code; branch on this"},"message":{"type":"string"},"fault":{"type":"string","description":"Who the failure is attributable to: customer, platform, provider"},"tips":{"type":"array","items":{"type":"string"}},"docsUrl":{"type":"string"}},"required":["error"],"additionalProperties":true}}}},"404":{"description":"No such experiment or run in this project","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable failure code; branch on this"},"message":{"type":"string"},"fault":{"type":"string","description":"Who the failure is attributable to: customer, platform, provider"},"tips":{"type":"array","items":{"type":"string"}},"docsUrl":{"type":"string"}},"required":["error"],"additionalProperties":true}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"runId","required":true}],"security":[{"project_api_key":[]}]}},"/api/experiments/runs/{runId}/results":{"get":{"operationId":"getApiExperimentsRunsByRunIdResults","summary":"Read run results","description":"Every dataset row of a run with what the target predicted, plus one entry per evaluator per row. Runs older than the status cache need `experimentSlug` as well, since a run id is only unique within its experiment.","tags":["Experiments"],"parameters":[{"in":"query","name":"experimentSlug","required":false,"schema":{"type":"string"},"description":"Owning experiment. Required once the run has aged out of the status cache."},{"schema":{"type":"string"},"in":"path","name":"runId","required":true}],"responses":{"200":{"description":"Rows and evaluations for the run","content":{"application/json":{"schema":{"type":"object","properties":{"experimentId":{"type":"string"},"runId":{"type":"string"},"projectId":{"type":"string"},"workflowVersionId":{"type":["string","null"]},"progress":{"type":["number","null"]},"total":{"type":["number","null"]},"targets":{"type":["array","null"],"items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"type":"string"},"promptId":{"type":["string","null"]},"promptVersion":{"type":["number","null"]},"agentId":{"type":["string","null"]},"evaluatorId":{"type":["string","null"]},"model":{"type":["string","null"]},"metadata":{"type":["object","null"],"additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"}]}}},"required":["id","name","type"]},"description":"Resolves the targetId each dataset row and evaluation carries"},"dataset":{"type":"array","items":{"type":"object","properties":{"index":{"type":"number"},"targetId":{"type":["string","null"]},"entry":{"type":"object","additionalProperties":{}},"predicted":{"type":"object","additionalProperties":{}},"cost":{"type":["number","null"]},"duration":{"type":["number","null"]},"error":{"type":["string","null"],"description":"The engine's own string. Prefer domainError.code to branch on"},"domainError":{"type":"object","properties":{"code":{"type":"string","description":"Stable failure code; branch on this"},"kind":{"type":"string","description":"Deprecated alias of code, for older clients"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"httpStatus":{"type":"number"},"fault":{"type":"string","description":"Who the failure is attributable to: customer, platform, provider"},"traceId":{"type":"string"},"tips":{"type":"array","items":{"type":"string"}},"docsUrl":{"type":"string"}},"required":["code","kind"],"description":"Set on rows written since failures started carrying codes"},"traceId":{"type":["string","null"]}},"required":["index","entry"]},"description":"One row per dataset entry, with what the target predicted"},"evaluations":{"type":"array","items":{"type":"object","properties":{"evaluator":{"type":"string"},"name":{"type":["string","null"]},"targetId":{"type":["string","null"]},"status":{"type":"string","enum":["processed","skipped","error"]},"index":{"type":"number"},"score":{"type":["number","null"]},"label":{"type":["string","null"]},"passed":{"type":["boolean","null"]},"details":{"type":["string","null"]},"cost":{"type":["number","null"]},"duration":{"type":["number","null"]},"inputs":{"type":["object","null"],"additionalProperties":{}}},"required":["evaluator","status","index"]},"description":"One row per evaluator per dataset entry"},"timestamps":{"type":"object","properties":{"createdAt":{"type":"number"},"updatedAt":{"type":"number"},"finishedAt":{"type":["number","null"]},"stoppedAt":{"type":["number","null"]}},"required":["createdAt","updatedAt"]}},"required":["experimentId","runId","projectId","dataset","evaluations","timestamps"]}}}},"401":{"description":"Missing or invalid API key, or the key lacks the permission","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable failure code; branch on this"},"message":{"type":"string"},"fault":{"type":"string","description":"Who the failure is attributable to: customer, platform, provider"},"tips":{"type":"array","items":{"type":"string"}},"docsUrl":{"type":"string"}},"required":["error"],"additionalProperties":true}}}},"404":{"description":"No such experiment or run in this project","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable failure code; branch on this"},"message":{"type":"string"},"fault":{"type":"string","description":"Who the failure is attributable to: customer, platform, provider"},"tips":{"type":"array","items":{"type":"string"}},"docsUrl":{"type":"string"}},"required":["error"],"additionalProperties":true}}}}},"security":[{"project_api_key":[]}]}},"/api/experiments/{slug}/workbench-state":{"get":{"operationId":"getApiExperimentsBySlugWorkbenchState","summary":"Read an experiment's setup","description":"The experiment's datasets, targets and evaluators, with the version to send back when you save. Ask for `fields=version` to check for changes without transferring the setup.","tags":["Experiments"],"parameters":[{"in":"query","name":"fields","required":false,"schema":{"type":"string","enum":["version"]},"description":"Set to `version` to answer with the version and timestamp only"},{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"The experiment's setup, or its version alone","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":["string","null"]},"state":{"type":["object","null"],"additionalProperties":{},"description":"The experiment setup: datasets, targets and evaluators. Read it, change it, send it back whole."},"version":{"type":"integer","description":"Send this back as expectedVersion to save safely"},"updatedAt":{"type":"string","description":"ISO 8601 timestamp of the last save"}},"required":["id","slug","name","state","version","updatedAt"]},{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"version":{"type":"integer"},"updatedAt":{"type":"string","description":"ISO 8601 timestamp of the last save"}},"required":["id","slug","version","updatedAt"]}]}}}},"400":{"description":"The experiment is not an evaluations workbench (experiment_type_mismatch)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable failure code; branch on this"},"message":{"type":"string"},"fault":{"type":"string","description":"Who the failure is attributable to: customer, platform, provider"},"tips":{"type":"array","items":{"type":"string"}},"docsUrl":{"type":"string"}},"required":["error"],"additionalProperties":true}}}},"401":{"description":"Missing or invalid API key, or the key lacks the permission","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable failure code; branch on this"},"message":{"type":"string"},"fault":{"type":"string","description":"Who the failure is attributable to: customer, platform, provider"},"tips":{"type":"array","items":{"type":"string"}},"docsUrl":{"type":"string"}},"required":["error"],"additionalProperties":true}}}},"404":{"description":"No such experiment or run in this project","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable failure code; branch on this"},"message":{"type":"string"},"fault":{"type":"string","description":"Who the failure is attributable to: customer, platform, provider"},"tips":{"type":"array","items":{"type":"string"}},"docsUrl":{"type":"string"}},"required":["error"],"additionalProperties":true}}}}},"security":[{"project_api_key":[]}]},"put":{"operationId":"putApiExperimentsBySlugWorkbenchState","summary":"Save an experiment's setup","description":"Replace the experiment's setup. Send `expectedVersion` with the version you read and the save is refused with a 409 when someone else wrote first, instead of overwriting their work.","tags":["Experiments"],"responses":{"200":{"description":"Setup saved","content":{"application/json":{"schema":{"type":"object","properties":{"version":{"type":"integer","description":"The version the save produced"}},"required":["version"]}}}},"400":{"description":"The setup did not match the schema (experiment_invalid_workbench_state), points at something that no longer exists (experiment_workbench_missing_reference), or the experiment is not an evaluations workbench (experiment_type_mismatch)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable failure code; branch on this"},"message":{"type":"string"},"fault":{"type":"string","description":"Who the failure is attributable to: customer, platform, provider"},"tips":{"type":"array","items":{"type":"string"}},"docsUrl":{"type":"string"}},"required":["error"],"additionalProperties":true}}}},"401":{"description":"Missing or invalid API key, or the key lacks the permission","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable failure code; branch on this"},"message":{"type":"string"},"fault":{"type":"string","description":"Who the failure is attributable to: customer, platform, provider"},"tips":{"type":"array","items":{"type":"string"}},"docsUrl":{"type":"string"}},"required":["error"],"additionalProperties":true}}}},"404":{"description":"No such experiment or run in this project","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable failure code; branch on this"},"message":{"type":"string"},"fault":{"type":"string","description":"Who the failure is attributable to: customer, platform, provider"},"tips":{"type":"array","items":{"type":"string"}},"docsUrl":{"type":"string"}},"required":["error"],"additionalProperties":true}}}},"409":{"description":"Someone else saved since you read this state (experiment_stale_workbench_state). `currentVersion` carries the version to read again.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable failure code; branch on this"},"message":{"type":"string"},"fault":{"type":"string","description":"Who the failure is attributable to: customer, platform, provider"},"tips":{"type":"array","items":{"type":"string"}},"docsUrl":{"type":"string"},"currentVersion":{"type":"integer","description":"The stored version now. Read the setup again at this one."}},"required":["error","currentVersion"],"additionalProperties":true}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"state":{"type":"object","additionalProperties":{},"description":"The full setup to save"},"expectedVersion":{"type":"integer","description":"The version you read. Sending it refuses the save when someone else already wrote on top of it."},"commitMessage":{"type":"string","description":"Names this version in the history list"}},"required":["state"]}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"security":[{"project_api_key":[]}]}},"/api/experiments/{slug}/versions":{"get":{"operationId":"getApiExperimentsBySlugVersions","summary":"List an experiment's versions","description":"Every saved version of the experiment's setup, newest first. A commit, an agent write and a restore each add a numbered version. Ordinary typing rewrites one autosave row, which is the entry with `autoSaved` true. Page through them with `limit` and `cursor`.","tags":["Experiments"],"parameters":[{"in":"query","name":"limit","required":false,"schema":{"type":"integer","default":50,"minimum":1,"maximum":100},"description":"Versions per page, capped at 100"},{"in":"query","name":"cursor","required":false,"schema":{"type":"integer","minimum":1},"description":"The `nextCursor` of the previous page"},{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Versions of the experiment","content":{"application/json":{"schema":{"type":"object","properties":{"versions":{"type":"array","items":{"type":"object","properties":{"version":{"type":"integer","description":"Restore this version by this number. Named versions run 1, 2, 3 with no gaps. The autosave row also has a number, but it changes with every save, so read it as a handle and not as a place in the history."},"counterVersion":{"type":"integer","description":"The setup version this row was written at. It says how recent the row is, and it equals the experiment's current version on the row holding the live setup."},"autoSaved":{"type":"boolean","description":"True for the single autosave row, which every ordinary save rewrites in place"},"commitMessage":{"type":["string","null"]},"authorLabel":{"type":"string","description":"Who wrote it: user, langy or api","example":"user"},"authorId":{"type":["string","null"],"description":"User id, when a person wrote it"},"createdAt":{"type":"string","description":"ISO 8601 timestamp of the first write"},"updatedAt":{"type":"string","description":"ISO 8601 timestamp of the last write. The autosave row is rewritten in place, so this is what says how old its content is."}},"required":["version","counterVersion","autoSaved","commitMessage","authorLabel","authorId","createdAt","updatedAt"]},"description":"Newest first, by `counterVersion`"},"nextCursor":{"type":["integer","null"],"description":"Pass as `cursor` to read the next page, null on the last one"}},"required":["versions","nextCursor"]}}}},"400":{"description":"The experiment is not an evaluations workbench (experiment_type_mismatch)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable failure code; branch on this"},"message":{"type":"string"},"fault":{"type":"string","description":"Who the failure is attributable to: customer, platform, provider"},"tips":{"type":"array","items":{"type":"string"}},"docsUrl":{"type":"string"}},"required":["error"],"additionalProperties":true}}}},"401":{"description":"Missing or invalid API key, or the key lacks the permission","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable failure code; branch on this"},"message":{"type":"string"},"fault":{"type":"string","description":"Who the failure is attributable to: customer, platform, provider"},"tips":{"type":"array","items":{"type":"string"}},"docsUrl":{"type":"string"}},"required":["error"],"additionalProperties":true}}}},"404":{"description":"No such experiment or run in this project","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable failure code; branch on this"},"message":{"type":"string"},"fault":{"type":"string","description":"Who the failure is attributable to: customer, platform, provider"},"tips":{"type":"array","items":{"type":"string"}},"docsUrl":{"type":"string"}},"required":["error"],"additionalProperties":true}}}}},"security":[{"project_api_key":[]}]}},"/api/experiments/{slug}/versions/{version}/restore":{"post":{"operationId":"postApiExperimentsBySlugVersionsByVersionRestore","summary":"Restore an experiment version","description":"Bring an old setup back by writing it forward as a new save. History is never rewritten: the version you restored from stays in the list, and the restore is one more entry after it.","tags":["Experiments"],"parameters":[{"in":"path","name":"version","required":true,"schema":{"type":"integer","minimum":1},"description":"The version to restore, as listed by `GET /api/experiments/{slug}/versions`"},{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Version restored","content":{"application/json":{"schema":{"type":"object","properties":{"version":{"type":"number","description":"The new version the restore wrote. History is never rewritten, so the restored version is still in the list."}},"required":["version"]}}}},"400":{"description":"The setup did not match the schema (experiment_invalid_workbench_state), points at something that no longer exists (experiment_workbench_missing_reference), or the experiment is not an evaluations workbench (experiment_type_mismatch)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable failure code; branch on this"},"message":{"type":"string"},"fault":{"type":"string","description":"Who the failure is attributable to: customer, platform, provider"},"tips":{"type":"array","items":{"type":"string"}},"docsUrl":{"type":"string"}},"required":["error"],"additionalProperties":true}}}},"401":{"description":"Missing or invalid API key, or the key lacks the permission","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable failure code; branch on this"},"message":{"type":"string"},"fault":{"type":"string","description":"Who the failure is attributable to: customer, platform, provider"},"tips":{"type":"array","items":{"type":"string"}},"docsUrl":{"type":"string"}},"required":["error"],"additionalProperties":true}}}},"404":{"description":"No such experiment or run in this project","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable failure code; branch on this"},"message":{"type":"string"},"fault":{"type":"string","description":"Who the failure is attributable to: customer, platform, provider"},"tips":{"type":"array","items":{"type":"string"}},"docsUrl":{"type":"string"}},"required":["error"],"additionalProperties":true}}}},"409":{"description":"Someone else saved since you read this state (experiment_stale_workbench_state). `currentVersion` carries the version to read again.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable failure code; branch on this"},"message":{"type":"string"},"fault":{"type":"string","description":"Who the failure is attributable to: customer, platform, provider"},"tips":{"type":"array","items":{"type":"string"}},"docsUrl":{"type":"string"},"currentVersion":{"type":"integer","description":"The stored version now. Read the setup again at this one."}},"required":["error","currentVersion"],"additionalProperties":true}}}}},"security":[{"project_api_key":[]}]}},"/api/analytics":{"post":{"operationId":"postApiAnalytics","summary":"Query analytics timeseries (legacy path)","description":"Query analytics timeseries with metrics, aggregations and filters. Identical to `POST /api/analytics/timeseries`, which is the path to use in new integrations; this one stays for callers written against it.","tags":["Analytics"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"startDate":{"type":"number","exclusiveMinimum":0},"endDate":{"type":"number","exclusiveMinimum":0},"query":{"type":"string"},"filters":{"type":"object","required":["topics.topics","topics.subtopics","metadata.user_id","metadata.thread_id","metadata.customer_id","metadata.labels","metadata.key","metadata.value","metadata.prompt_ids","traces.origin","traces.error","traces.name","spans.type","spans.model","evaluations.evaluator_id","evaluations.evaluator_id.guardrails_only","evaluations.evaluator_id.has_passed","evaluations.evaluator_id.has_score","evaluations.evaluator_id.has_label","evaluations.passed","evaluations.score","evaluations.state","evaluations.label","events.event_type","events.metrics.key","events.metrics.value","events.event_details.key","annotations.hasAnnotation"],"properties":{"topics.topics":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"topics.subtopics":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"metadata.user_id":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"metadata.thread_id":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"metadata.customer_id":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"metadata.labels":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"metadata.key":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"metadata.value":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"metadata.prompt_ids":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"traces.origin":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"traces.error":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"traces.name":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"spans.type":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"spans.model":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.evaluator_id":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.evaluator_id.guardrails_only":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.evaluator_id.has_passed":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.evaluator_id.has_score":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.evaluator_id.has_label":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.passed":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.score":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.state":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.label":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"events.event_type":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"events.metrics.key":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"events.metrics.value":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"events.event_details.key":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"annotations.hasAnnotation":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]}},"additionalProperties":false,"default":{}},"traceIds":{"type":"array","items":{"type":"string"}},"negateFilters":{"type":"boolean"},"excludeOrigins":{"type":"array","items":{"type":"string"}},"series":{"type":"array","items":{"type":"object","properties":{"metric":{"type":"string","enum":["metadata.trace_id","metadata.user_id","metadata.thread_id","metadata.span_type","sentiment.thumbs_up_down","performance.completion_time","performance.first_token","performance.total_cost","performance.cost_billed","performance.cost_non_billed","performance.prompt_tokens","performance.completion_tokens","performance.cache_read_tokens","performance.cache_write_tokens","performance.reasoning_tokens","performance.total_processed_tokens","performance.total_tokens","performance.tokens_per_second","events.event_type","events.event_score","events.event_details","evaluations.evaluation_score","evaluations.evaluation_pass_rate","evaluations.evaluation_runs","threads.average_duration_per_thread"]},"key":{"type":"string"},"subkey":{"type":"string"},"aggregation":{"type":"string","enum":["terms","cardinality","avg","sum","min","max","median","p99","p95","p90"]},"pipeline":{"type":"object","properties":{"field":{"type":"string","enum":["trace_id","user_id","thread_id","customer_id"]},"aggregation":{"type":"string","enum":["sum","avg","min","max"]}},"required":["field","aggregation"],"additionalProperties":false},"filters":{"type":"object","required":["topics.topics","topics.subtopics","metadata.user_id","metadata.thread_id","metadata.customer_id","metadata.labels","metadata.key","metadata.value","metadata.prompt_ids","traces.origin","traces.error","traces.name","spans.type","spans.model","evaluations.evaluator_id","evaluations.evaluator_id.guardrails_only","evaluations.evaluator_id.has_passed","evaluations.evaluator_id.has_score","evaluations.evaluator_id.has_label","evaluations.passed","evaluations.score","evaluations.state","evaluations.label","events.event_type","events.metrics.key","events.metrics.value","events.event_details.key","annotations.hasAnnotation"],"properties":{"topics.topics":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"topics.subtopics":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"metadata.user_id":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"metadata.thread_id":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"metadata.customer_id":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"metadata.labels":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"metadata.key":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"metadata.value":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"metadata.prompt_ids":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"traces.origin":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"traces.error":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"traces.name":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"spans.type":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"spans.model":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.evaluator_id":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.evaluator_id.guardrails_only":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.evaluator_id.has_passed":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.evaluator_id.has_score":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.evaluator_id.has_label":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.passed":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.score":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.state":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.label":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"events.event_type":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"events.metrics.key":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"events.metrics.value":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"events.event_details.key":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"annotations.hasAnnotation":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]}},"additionalProperties":false},"asPercent":{"type":"boolean"}},"required":["metric","aggregation"],"additionalProperties":false}},"groupBy":{"type":"string","enum":["topics.topics","traces.trace_name","metadata.user_id","metadata.thread_id","metadata.customer_id","metadata.labels","metadata.model","metadata.span_type","sentiment.thumbs_up_down","events.event_type","evaluations.evaluation_passed","evaluations.evaluation_label","evaluations.evaluation_processing_state","error.has_error"]},"groupByKey":{"type":"string"},"timeScale":{"anyOf":[{"type":"string","enum":["full"]},{"type":"integer"}]},"timeZone":{"type":"string"}},"required":["startDate","endDate","series","timeZone"],"additionalProperties":false}}}},"responses":{"200":{"description":"Timeseries data for the requested range and the one before it","content":{"application/json":{"schema":{"type":"object","properties":{"currentPeriod":{"type":"array","items":{"type":"object","additionalProperties":{}},"description":"One row per time bucket over the requested range"},"previousPeriod":{"type":"array","items":{"type":"object","additionalProperties":{}},"description":"The same range shifted back by its own length, for comparison"}},"required":["currentPeriod","previousPeriod"]}}}},"400":{"description":"The body was not valid JSON, or failed validation","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Set when the request was rejected before validation"},"error":{"type":"string","description":"Set when the body parsed and then failed validation"}}}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}},"403":{"description":"The API key lacks analytics:view","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable failure code; branch on this"},"message":{"type":"string"},"fault":{"type":"string","description":"Who the failure is attributable to: customer, platform, provider"},"tips":{"type":"array","items":{"type":"string"}},"docsUrl":{"type":"string"}},"required":["error"],"additionalProperties":true}}}}},"security":[{"project_api_key":[]}]}},"/api/dspy/log_steps":{"post":{"operationId":"postApiDspyLogSteps","summary":"Report DSPy optimizer steps","description":"Report the steps of a DSPy optimizer run against an experiment, so the run's progress and scores show up in the app. Send the steps as an array; the optimizer typically posts each batch as it finishes. Bodies up to 20MB are accepted.","tags":["Experiments"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","items":{"allOf":[{"type":"object","properties":{"run_id":{"type":"string"},"workflow_version_id":{"type":"string","nullable":true},"index":{"type":"string"},"score":{"type":"number"},"label":{"type":"string"},"optimizer":{"type":"object","properties":{"name":{"type":"string"},"parameters":{"type":"object","additionalProperties":{}}},"required":["name","parameters"],"additionalProperties":false},"predictors":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"predictor":{"allOf":[{"type":"object","properties":{"__class__":{"type":"string"}}},{"type":"object","additionalProperties":{}}]}},"required":["name","predictor"],"additionalProperties":false}}},"required":["run_id","index","score","label","optimizer","predictors"]},{"type":"object","properties":{"experiment_id":{"type":"string","nullable":true},"experiment_slug":{"type":"string","nullable":true},"timestamps":{"type":"object","properties":{"created_at":{"type":"number"}},"required":["created_at"],"additionalProperties":false},"examples":{"type":"array","items":{"type":"object","properties":{"example":{"allOf":[{"type":"object","properties":{"__class__":{"type":"string"}}},{"type":"object","additionalProperties":{}}]},"pred":{"allOf":[{"type":"object","properties":{"__class__":{"type":"string"}}},{"type":"object","additionalProperties":{}}]},"score":{"type":"number"},"trace":{"type":"array","items":{"type":"object","properties":{"input":{"allOf":[{"type":"object","properties":{"__class__":{"type":"string"}}},{"type":"object","additionalProperties":{}}]},"pred":{"allOf":[{"type":"object","properties":{"__class__":{"type":"string"}}},{"type":"object","additionalProperties":{}}]}},"required":["input","pred"],"additionalProperties":false},"nullable":true}},"required":["example","pred","score"],"additionalProperties":false}},"llm_calls":{"type":"array","items":{"type":"object","properties":{"__class__":{"type":"string"},"response":{"allOf":[{"type":"object","properties":{"__class__":{"type":"string"}}},{"type":"object","additionalProperties":{}}]},"model":{"type":"string","nullable":true},"prompt_tokens":{"type":"number","nullable":true},"completion_tokens":{"type":"number","nullable":true},"cost":{"type":"number","nullable":true}},"required":["__class__","response"],"additionalProperties":false}}},"required":["timestamps","examples","llm_calls"]}]}}}}},"responses":{"200":{"description":"Every step in the batch was recorded","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable confirmation"}},"required":["message"]}}}},"400":{"description":"The body was not valid JSON, failed validation, or carried timestamps in seconds rather than milliseconds","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Set when the request was rejected before validation"},"error":{"type":"string","description":"Set when the body parsed and then failed validation"}}}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}},"403":{"description":"The API key lacks experiments:manage","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable failure code; branch on this"},"message":{"type":"string"},"fault":{"type":"string","description":"Who the failure is attributable to: customer, platform, provider"},"tips":{"type":"array","items":{"type":"string"}},"docsUrl":{"type":"string"}},"required":["error"],"additionalProperties":true}}}},"500":{"description":"A step could not be stored. The cause is on our side and is logged with the run and step ids; retrying the batch is safe.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Set when the request was rejected before validation"},"error":{"type":"string","description":"Set when the body parsed and then failed validation"}}}}}}},"security":[{"project_api_key":[]}]}},"/api/experiment/init":{"post":{"operationId":"postApiExperimentInit","summary":"Create an experiment","description":"Create an experiment, or return the existing one when the slug is already taken. This is the first call in an experiment run: take the slug back, report results against it, and every run under that slug groups together in the app. The SDKs call this endpoint for you.","tags":["Experiments"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"experiment_slug":{"type":"string","description":"Stable slug you choose. Reusing it returns the same experiment instead of creating another, which is what makes repeated runs land together."},"experiment_id":{"type":"string","description":"Existing experiment id, as an alternative to the slug"},"experiment_type":{"type":"string","enum":["DSPY","BATCH_EVALUATION","BATCH_EVALUATION_V2"],"description":"BATCH_EVALUATION_V2 for SDK batch evaluations, DSPY for optimizer runs"},"experiment_name":{"type":"string","description":"Display name, used only when the experiment is created"},"workflowId":{"type":"string","description":"Optimization Studio workflow this experiment belongs to"}},"required":["experiment_type"],"anyOf":[{"required":["experiment_slug"]},{"required":["experiment_id"]}]}}}},"responses":{"200":{"description":"The experiment, created or already existing","content":{"application/json":{"schema":{"type":"object","properties":{"slug":{"type":"string","description":"Slug of the experiment, created or existing"},"path":{"type":"string","description":"Path to the experiment in the LangWatch app"}},"required":["slug","path"]}}}},"400":{"description":"The body was not valid JSON, or neither experiment_slug nor experiment_id was supplied","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"message":{"type":"string","description":"Set when the body was not valid JSON"}},"required":["message"]},{"type":"object","properties":{"error":{"type":"string","description":"The validation failure as a sentence, not a code: neither identifier was supplied, or a field had the wrong type"}},"required":["error"]}]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}},"403":{"description":"The API key lacks experiments:manage, or the plan's experiment limit is already reached","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable failure code; branch on this"},"message":{"type":"string"},"fault":{"type":"string","description":"Who the failure is attributable to: customer, platform, provider"},"tips":{"type":"array","items":{"type":"string"}},"docsUrl":{"type":"string"},"limitType":{"type":"string","description":"Which plan limit was reached, on resource_limit_exceeded"},"current":{"type":"number","description":"Experiments already in use"},"max":{"type":"number","description":"What the plan allows"}},"required":["error"],"additionalProperties":true}}}}},"security":[{"project_api_key":[]}]}},"/api/optimization/{workflowId}/{versionId}":{"post":{"operationId":"postApiOptimizationByWorkflowIdByVersionId","summary":"Run a workflow version (legacy path)","description":"Run one pinned version of an Optimization Studio workflow synchronously. Identical to `POST /api/workflows/{workflowId}/{versionId}/run`, which is the path to use in new integrations; this one stays for callers written against it.","tags":["Workflows"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"description":"The workflow's input fields, named as the workflow's entry node names them"}}}},"responses":{"200":{"description":"The workflow finished; `result` holds its output fields","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["idle","waiting","running","success","error","skipped"],"description":"Execution state the run finished in"},"result":{"type":["object","null"],"additionalProperties":{},"description":"The workflow's output fields, named as the workflow names them"}},"required":["status"]}}}},"400":{"description":"The request was not sent as application/json, or the body was not valid JSON","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}},"403":{"description":"The API key lacks workflows:manage","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable failure code; branch on this"},"message":{"type":"string"},"fault":{"type":"string","description":"Who the failure is attributable to: customer, platform, provider"},"tips":{"type":"array","items":{"type":"string"}},"docsUrl":{"type":"string"}},"required":["error"],"additionalProperties":true}}}},"404":{"description":"No such workflow, or it has never been published","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable failure code; branch on this"},"message":{"type":"string"},"fault":{"type":"string","description":"Who the failure is attributable to: customer, platform, provider"},"tips":{"type":"array","items":{"type":"string"}},"docsUrl":{"type":"string"}},"required":["error"],"additionalProperties":true}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"workflowId","required":true},{"schema":{"type":"string"},"in":"path","name":"versionId","required":true}],"security":[{"project_api_key":[]}]}},"/api/track_event":{"post":{"operationId":"postApiTrackEvent","summary":"Track an event (legacy path)","description":"Record a customer event against a trace or thread. Identical to `POST /api/events/track`, which is the path to use in new integrations; this one stays for callers written against it. Supply `event_id` yourself to make the call idempotent.","tags":["Events"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"type":"object","properties":{"event_type":{"type":"string"},"metrics":{"type":"object","additionalProperties":{"type":"number"}},"trace_id":{"type":"string"}},"required":["event_type","metrics","trace_id"]},{"type":"object","properties":{"event_id":{"type":"string"},"event_details":{"type":"object","additionalProperties":{"type":"string","nullable":true}},"timestamp":{"type":"number"}}}]}}}},"responses":{"200":{"description":"The event was accepted","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable confirmation"}},"required":["message"]}}}},"400":{"description":"The body was not valid JSON, or failed validation","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Set when the request was rejected before validation"},"error":{"type":"string","description":"Set when the body parsed and then failed validation"}}}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}},"403":{"description":"The API key lacks traces:create","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable failure code; branch on this"},"message":{"type":"string"},"fault":{"type":"string","description":"Who the failure is attributable to: customer, platform, provider"},"tips":{"type":"array","items":{"type":"string"}},"docsUrl":{"type":"string"}},"required":["error"],"additionalProperties":true}}}}},"security":[{"project_api_key":[]}]}},"/api/trigger/slack":{"post":{"operationId":"postApiTriggerSlack","summary":"Create a Slack alert trigger","description":"Create a trigger that posts to Slack when traces match its filters, through a Slack connection (`slack_connection_id`, plus `slack_channel_id` for a bot) or an incoming webhook URL (`slack_webhook`), which is stored as a connection. The trigger stores no secret of its own. The `/api/triggers` family supersedes this narrower form, which stays for callers written against it.","tags":["Triggers"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"slack_webhook":{"type":"string","format":"uri","description":"Incoming webhook URL the alert is posted to. It is stored as a Slack connection this project can use (an existing one holding the same URL, else a new project connection). Send this or `slack_connection_id`, not both."},"slack_connection_id":{"type":"string","minLength":1,"description":"The Slack connection the alert posts through: an organization connection or one of this project's, as `GET /api/slack-connections` and `langwatch slack-connection list` list them. Send this or `slack_webhook`, not both."},"slack_channel_id":{"type":"string","minLength":1,"description":"The channel a bot connection posts in; required with one. Invite the LangWatch app to it first."},"name":{"type":"string","description":"How the trigger is listed in the app"},"message":{"type":"string","description":"Extra line included with each alert"},"filters":{"type":"object","required":["topics.topics","topics.subtopics","metadata.user_id","metadata.thread_id","metadata.customer_id","metadata.labels","metadata.key","metadata.value","metadata.prompt_ids","traces.origin","traces.error","traces.name","spans.type","spans.model","evaluations.evaluator_id","evaluations.evaluator_id.guardrails_only","evaluations.evaluator_id.has_passed","evaluations.evaluator_id.has_score","evaluations.evaluator_id.has_label","evaluations.passed","evaluations.score","evaluations.state","evaluations.label","events.event_type","events.metrics.key","events.metrics.value","events.event_details.key","annotations.hasAnnotation"],"properties":{"topics.topics":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"topics.subtopics":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"metadata.user_id":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"metadata.thread_id":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"metadata.customer_id":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"metadata.labels":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"metadata.key":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"metadata.value":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"metadata.prompt_ids":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"traces.origin":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"traces.error":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"traces.name":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"spans.type":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"spans.model":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.evaluator_id":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.evaluator_id.guardrails_only":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.evaluator_id.has_passed":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.evaluator_id.has_score":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.evaluator_id.has_label":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.passed":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.score":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.state":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.label":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"events.event_type":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"events.metrics.key":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"events.metrics.value":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"events.event_details.key":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"annotations.hasAnnotation":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]}},"additionalProperties":false,"default":{},"description":"Which traces the trigger fires on. An empty object fires on all of them."},"alert_type":{"type":"string","enum":["CRITICAL","WARNING","INFO"]}},"required":["name","alert_type"],"additionalProperties":false}}}},"responses":{"200":{"description":"The trigger was created","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable confirmation"}},"required":["message"]}}}},"400":{"description":"The body was not valid JSON, or failed validation","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"errors":{"type":"array","items":{"type":"object","additionalProperties":{}},"description":"The individual validation failures, when present"}},"required":["message"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}},"403":{"description":"The API key lacks triggers:manage","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable failure code; branch on this"},"message":{"type":"string"},"fault":{"type":"string","description":"Who the failure is attributable to: customer, platform, provider"},"tips":{"type":"array","items":{"type":"string"}},"docsUrl":{"type":"string"}},"required":["error"],"additionalProperties":true}}}},"422":{"description":"The connection is not one this project can use (`slack_integration_missing`), or a bot connection was named without `slack_channel_id` (`invalid_action_params`)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable failure code; branch on this"},"message":{"type":"string"},"fault":{"type":"string","description":"Who the failure is attributable to: customer, platform, provider"},"tips":{"type":"array","items":{"type":"string"}},"docsUrl":{"type":"string"}},"required":["error"],"additionalProperties":true}}}}},"security":[{"project_api_key":[]}]}},"/api/workflows/{workflowId}/run":{"post":{"operationId":"postApiWorkflowsByWorkflowIdRun","summary":"Run a workflow","description":"Run an Optimization Studio workflow synchronously and return its output. Runs the workflow's published version; address a specific version with the `{versionId}` form of this path.","tags":["Workflows"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"description":"The workflow's input fields, named as the workflow's entry node names them"}}}},"responses":{"200":{"description":"The workflow finished; `result` holds its output fields","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["idle","waiting","running","success","error","skipped"],"description":"Execution state the run finished in"},"result":{"type":["object","null"],"additionalProperties":{},"description":"The workflow's output fields, named as the workflow names them"}},"required":["status"]}}}},"400":{"description":"The request was not sent as application/json, or the body was not valid JSON","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}},"403":{"description":"The API key lacks workflows:manage","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable failure code; branch on this"},"message":{"type":"string"},"fault":{"type":"string","description":"Who the failure is attributable to: customer, platform, provider"},"tips":{"type":"array","items":{"type":"string"}},"docsUrl":{"type":"string"}},"required":["error"],"additionalProperties":true}}}},"404":{"description":"No such workflow, or it has never been published","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable failure code; branch on this"},"message":{"type":"string"},"fault":{"type":"string","description":"Who the failure is attributable to: customer, platform, provider"},"tips":{"type":"array","items":{"type":"string"}},"docsUrl":{"type":"string"}},"required":["error"],"additionalProperties":true}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"workflowId","required":true}],"security":[{"project_api_key":[]}]}},"/api/workflows/{workflowId}/{versionId}/run":{"post":{"operationId":"postApiWorkflowsByWorkflowIdByVersionIdRun","summary":"Run a specific workflow version","description":"Run one pinned version of an Optimization Studio workflow synchronously and return its output. Use this when a caller must keep hitting the same version as the workflow is edited.","tags":["Workflows"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"description":"The workflow's input fields, named as the workflow's entry node names them"}}}},"responses":{"200":{"description":"The workflow finished; `result` holds its output fields","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["idle","waiting","running","success","error","skipped"],"description":"Execution state the run finished in"},"result":{"type":["object","null"],"additionalProperties":{},"description":"The workflow's output fields, named as the workflow names them"}},"required":["status"]}}}},"400":{"description":"The request was not sent as application/json, or the body was not valid JSON","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}},"403":{"description":"The API key lacks workflows:manage","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable failure code; branch on this"},"message":{"type":"string"},"fault":{"type":"string","description":"Who the failure is attributable to: customer, platform, provider"},"tips":{"type":"array","items":{"type":"string"}},"docsUrl":{"type":"string"}},"required":["error"],"additionalProperties":true}}}},"404":{"description":"No such workflow, or it has never been published","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable failure code; branch on this"},"message":{"type":"string"},"fault":{"type":"string","description":"Who the failure is attributable to: customer, platform, provider"},"tips":{"type":"array","items":{"type":"string"}},"docsUrl":{"type":"string"}},"required":["error"],"additionalProperties":true}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"workflowId","required":true},{"schema":{"type":"string"},"in":"path","name":"versionId","required":true}],"security":[{"project_api_key":[]}]}},"/api/checkup":{"get":{"operationId":"getApiCheckup","summary":"Run the free checks of a self-hosted install","description":"The checkup `langwatch doctor` and the Settings > Checkup page show: one row per check with a pass, fail or not checked verdict. Checks that open a connection or spend money are reported as not checked here and run through `POST /api/checkup/run`. The response also carries the usage report this install would send next. Answers 404 on LangWatch Cloud.","tags":["Checkup"],"responses":{"200":{"description":"The checkup report and the usage report preview.","content":{"application/json":{"schema":{"type":"object","properties":{"ranAt":{"type":"string","format":"date-time"},"rows":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The check, one of the ids `POST /api/checkup/run` accepts."},"name":{"type":"string"},"group":{"type":"string","enum":["install","langwatch","integrations","pipelines"]},"cost":{"type":"string","enum":["free","egress","paid"],"description":"Free checks run on every call; egress and paid ones only through `POST /api/checkup/run`."},"verdict":{"type":"object","properties":{"outcome":{"type":"string","enum":["verified","refused","unchecked"]},"detail":{"type":"string"},"code":{"type":"string","description":"Present on a refused verdict: the stable error code."},"fix":{"type":"string"},"docsPath":{"type":"string"}},"required":["outcome","detail"]}},"required":["id","name","group","cost","verdict"]}},"usageReport":{"type":"object","additionalProperties":true}},"required":["ranAt","rows","usageReport"]}}}},"404":{"description":"The install is LangWatch Cloud, or the key's project has no organization."}},"security":[{"project_api_key":[]}]}},"/api/checkup/run":{"post":{"operationId":"postApiCheckupRun","summary":"Run the checks that open a connection or spend money","description":"Runs the egress and paid checks of a self-hosted install: reaching the connect and gateway hosts, the storage write, the SMTP connection, one model provider call and the pipeline canaries. Name the checks to run, or leave the list out to run them all. The scenario canary launches a real run and needs a run plan id. Answers 404 on LangWatch Cloud.","tags":["Checkup"],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"checks":{"type":"array","items":{"type":"string"},"description":"The check ids to run. Omit to run every explicit check."},"scenarioRunPlanId":{"type":"string","description":"The run plan the scenario canary launches."}}}}}},"responses":{"200":{"description":"The rows of the checks that ran.","content":{"application/json":{"schema":{"type":"object","properties":{"ranAt":{"type":"string","format":"date-time"},"rows":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The check, one of the ids `POST /api/checkup/run` accepts."},"name":{"type":"string"},"group":{"type":"string","enum":["install","langwatch","integrations","pipelines"]},"cost":{"type":"string","enum":["free","egress","paid"],"description":"Free checks run on every call; egress and paid ones only through `POST /api/checkup/run`."},"verdict":{"type":"object","properties":{"outcome":{"type":"string","enum":["verified","refused","unchecked"]},"detail":{"type":"string"},"code":{"type":"string","description":"Present on a refused verdict: the stable error code."},"fix":{"type":"string"},"docsPath":{"type":"string"}},"required":["outcome","detail"]}},"required":["id","name","group","cost","verdict"]}}},"required":["ranAt","rows"]}}}},"404":{"description":"The install is LangWatch Cloud, or the key's project has no organization."}},"security":[{"project_api_key":[]}]}},"/api/gateway/v1/virtual-keys":{"get":{"operationId":"getApiGatewayV1VirtualKeys","summary":"List virtual keys","description":"Returns the virtual keys visible to the caller's project credential: keys scoped to this project, to its team, or to the whole organization. Newest first, paged by cursor: follow `next_cursor` until it comes back null. Visibility is applied to each page after it is read, so a page can hold fewer than `limit` rows without meaning the walk is finished.","tags":["Virtual Keys"],"responses":{"200":{"description":"Visible virtual keys","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"organization_id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"status":{"type":"string","enum":["active","disabled","revoked"]},"purpose":{"type":"string","enum":["user","langy"]},"display_prefix":{"type":"string"},"principal_user_id":{"type":["string","null"]},"trace_project_id":{"type":["string","null"],"description":"The project this key's traces and costs land in, which is the project its spend is attributed to. Not a scope: it grants no access to the key. Decided when the key is written and stored on it, so editing what the key is scoped to never moves it; send `trace_project_id` on an update to move it. Null only on a key created before this was stored, in an organization that had no governance project to fall back to; those keys export no spans until they are given a destination."},"trace_project_archived":{"type":"boolean","description":"True when the project in `trace_project_id` has been deleted. The key goes on sending its traces there, so the data stays whole and reappears if the project is restored, and traffic is never refused for it. Nothing else on the key says the destination is gone."},"external_id":{"type":["string","null"]},"metadata":{"type":"object","additionalProperties":{"type":"string"}},"scopes":{"type":"array","items":{"type":"object","properties":{"scope_type":{"type":"string","enum":["organization","team","project"]},"scope_id":{"type":"string"}},"required":["scope_type","scope_id"]}},"routing_policy_id":{"type":["string","null"]},"routing_mode":{"type":"string","enum":["none","fallback_all","policy"]},"config":{},"revision":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"last_used_at":{"type":["string","null"],"format":"date-time"},"revoked_at":{"type":["string","null"],"format":"date-time"},"expires_at":{"type":["string","null"],"format":"date-time","description":"When the key stops serving, or null for a key that never expires. Requests presented after this moment are refused with `virtual_key_expired`. `status` stays `active` past the date on purpose: the three status values are what clients switch on, and the key stays editable so the date can be extended."}},"required":["id","organization_id","name","description","status","purpose","display_prefix","principal_user_id","trace_project_id","trace_project_archived","external_id","metadata","scopes","routing_policy_id","routing_mode","revision","created_at","updated_at","last_used_at","revoked_at","expires_at"]}},"next_cursor":{"type":["string","null"],"description":"Pass back as `cursor` for the next page. Null means the walk is exhausted; a full page does NOT mean there is more."}},"required":["data","next_cursor"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"parameters":[{"in":"query","name":"cursor","schema":{"type":"string","maxLength":500}},{"in":"query","name":"limit","schema":{"type":"integer","exclusiveMinimum":0,"maximum":200,"default":50}},{"in":"query","name":"external_id","schema":{"type":"string","maxLength":128},"description":"Exact match on the resource's `external_id`."}],"security":[{"project_api_key":[]}]},"post":{"operationId":"postApiGatewayV1VirtualKeys","summary":"Create virtual key","description":"Mints a new virtual key and returns the secret exactly once. The caller MUST persist the `secret` value, because LangWatch stores only a hash. With `reveal_once` the response withholds the secret and carries `reveal_id` and `preview` instead: the secret is parked for 24 hours and served once, to the person the key is for, through the LangWatch app, so a caller that only relays the key (an agent printing a snippet) never holds it. `scopes` defaults to the caller's project, where `virtualKeys:create` is enough; org- and team-scoped keys, or a key for another project, require a scoped API key holding `virtualKeys:manage` at each requested scope. An org- or team-scoped key also needs a place for its traces and spend to land, and must say where: pass `trace_project_id` (needs `virtualKeys:manage` on that project). Without it, and without exactly one project scope to take it from, creation refuses with `gateway_trace_project_ambiguous`, because the spend would be attributed to the organization's hidden governance project and counted by no budget on the project you had in mind. An organization whose only project is the governance one is exempt, since there is nothing else to name; one with no governance project either refuses with `trace_project_required`. Send `Idempotency-Key` to make a retry safe: a replay returns the original response including its `secret`, which is the only way to recover a secret whose response was lost in transit.","tags":["Virtual Keys"],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"A caller-chosen key, 8 to 255 characters, that makes this create safe to retry. The first request to use a key runs normally and its response is stored for 24 hours. A later request with the same key and the same body is not executed again: it returns the stored response, marked with `X-Idempotent-Replay: true`. The same key with a different body is refused 409 `idempotency_error`, as is a retry sent while the original is still running. Only successful responses are stored, so a create that failed can simply be retried with the same key.","schema":{"type":"string","minLength":8,"maxLength":255}}],"responses":{"201":{"description":"Virtual key created","headers":{"X-Idempotent-Replay":{"description":"Present and `true` only when this body came from a stored response rather than a fresh execution. Absent on the first use of a key, and on every request that carries no key.","schema":{"type":"string","enum":["true"]}}},"content":{"application/json":{"schema":{"type":"object","properties":{"virtual_key":{"type":"object","properties":{"id":{"type":"string"},"organization_id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"status":{"type":"string","enum":["active","disabled","revoked"]},"purpose":{"type":"string","enum":["user","langy"]},"display_prefix":{"type":"string"},"principal_user_id":{"type":["string","null"]},"trace_project_id":{"type":["string","null"],"description":"The project this key's traces and costs land in, which is the project its spend is attributed to. Not a scope: it grants no access to the key. Decided when the key is written and stored on it, so editing what the key is scoped to never moves it; send `trace_project_id` on an update to move it. Null only on a key created before this was stored, in an organization that had no governance project to fall back to; those keys export no spans until they are given a destination."},"trace_project_archived":{"type":"boolean","description":"True when the project in `trace_project_id` has been deleted. The key goes on sending its traces there, so the data stays whole and reappears if the project is restored, and traffic is never refused for it. Nothing else on the key says the destination is gone."},"external_id":{"type":["string","null"]},"metadata":{"type":"object","additionalProperties":{"type":"string"}},"scopes":{"type":"array","items":{"type":"object","properties":{"scope_type":{"type":"string","enum":["organization","team","project"]},"scope_id":{"type":"string"}},"required":["scope_type","scope_id"]}},"routing_policy_id":{"type":["string","null"]},"routing_mode":{"type":"string","enum":["none","fallback_all","policy"]},"config":{},"revision":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"last_used_at":{"type":["string","null"],"format":"date-time"},"revoked_at":{"type":["string","null"],"format":"date-time"},"expires_at":{"type":["string","null"],"format":"date-time","description":"When the key stops serving, or null for a key that never expires. Requests presented after this moment are refused with `virtual_key_expired`. `status` stays `active` past the date on purpose: the three status values are what clients switch on, and the key stays editable so the date can be extended."}},"required":["id","organization_id","name","description","status","purpose","display_prefix","principal_user_id","trace_project_id","trace_project_archived","external_id","metadata","scopes","routing_policy_id","routing_mode","revision","created_at","updated_at","last_used_at","revoked_at","expires_at"]},"secret":{"type":"string","description":"The secret, absent when `reveal_once` was set."},"reveal_id":{"type":"string","description":"With `reveal_once`: the id that serves the secret once, through the app."},"preview":{"type":"string","description":"With `reveal_once`: the key's display prefix, safe to show in place of the secret."}},"required":["virtual_key"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Caller lacks virtualKeys:create on its own project, or virtualKeys:manage at a scope beyond it","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":128},"description":{"type":"string"},"principal_user_id":{"type":["string","null"]},"reveal_once":{"type":"boolean"},"scopes":{"type":"array","items":{"type":"object","properties":{"scope_type":{"type":"string","enum":["organization","team","project"]},"scope_id":{"type":"string","minLength":1}},"required":["scope_type","scope_id"]},"minItems":1},"trace_project_id":{"type":["string","null"]},"routing_policy_id":{"type":["string","null"]},"routing_mode":{"type":"string","enum":["none","fallback_all","policy"]},"expires_at":{"type":"string","description":"When the key stops serving. Omit it and the key never expires. A date that has already passed is refused with `virtual_key_expiry_in_past`, rather than writing a key that is dead on arrival."},"budget":{"type":["object","null"],"properties":{"limit_usd":{"anyOf":[{"type":"number","exclusiveMinimum":0},{"type":"string","pattern":"^\\d+(\\.\\d+)?$"}]},"window":{"type":"string","enum":["day","week","month"]},"on_breach":{"type":"string","enum":["block","warn"]},"name":{"type":"string","minLength":1,"maxLength":128}},"required":["limit_usd","window"]},"config":{"type":"object","properties":{"modelsAllowed":{"type":["array","null"],"items":{"type":"string"},"default":null},"providersAllowed":{"type":["array","null"],"items":{"type":"string"},"default":null},"cache":{"type":"object","properties":{"mode":{"type":"string","enum":["respect","force","disable"],"default":"respect"},"ttlS":{"type":"integer","minimum":0,"default":3600}},"default":{"mode":"respect","ttlS":3600}},"fallback":{"type":"object","properties":{"maxAttempts":{"type":"integer","exclusiveMinimum":0,"default":3}},"default":{"maxAttempts":3}},"guardrailAttachments":{"type":"array","items":{"type":"object","properties":{"direction":{"type":"string","enum":["pre","post","stream_chunk"]},"guardrailIds":{"type":"array","items":{"type":"string"},"default":[]}},"required":["direction"]},"default":[]},"rateLimits":{"type":"object","properties":{"rpm":{"type":["integer","null"],"default":null},"tpm":{"type":["integer","null"],"default":null},"rpd":{"type":["integer","null"],"default":null}},"default":{"rpm":null,"tpm":null,"rpd":null}},"realtime":{"type":"object","properties":{"maxOpenSessions":{"type":["integer","null"],"exclusiveMinimum":0,"default":null}},"default":{"maxOpenSessions":null}},"metadata":{"type":"object","properties":{"label":{"type":"string"},"tags":{"type":"array","items":{"type":"string"},"default":[]}},"default":{"tags":[]}}}},"external_id":{"type":["string","null"],"minLength":1,"maxLength":128},"metadata":{"type":"object","propertyNames":{"type":"string","minLength":1,"maxLength":64},"additionalProperties":{"type":"string","maxLength":500}},"purpose":{"type":"string","const":"user"}},"required":["name"]}}}},"security":[{"project_api_key":[]}]}},"/api/gateway/v1/virtual-keys/{id}":{"get":{"operationId":"getApiGatewayV1VirtualKeysById","summary":"Get virtual key","tags":["Virtual Keys"],"responses":{"200":{"description":"Virtual key detail","content":{"application/json":{"schema":{"type":"object","properties":{"virtual_key":{"type":"object","properties":{"id":{"type":"string"},"organization_id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"status":{"type":"string","enum":["active","disabled","revoked"]},"purpose":{"type":"string","enum":["user","langy"]},"display_prefix":{"type":"string"},"principal_user_id":{"type":["string","null"]},"trace_project_id":{"type":["string","null"],"description":"The project this key's traces and costs land in, which is the project its spend is attributed to. Not a scope: it grants no access to the key. Decided when the key is written and stored on it, so editing what the key is scoped to never moves it; send `trace_project_id` on an update to move it. Null only on a key created before this was stored, in an organization that had no governance project to fall back to; those keys export no spans until they are given a destination."},"trace_project_archived":{"type":"boolean","description":"True when the project in `trace_project_id` has been deleted. The key goes on sending its traces there, so the data stays whole and reappears if the project is restored, and traffic is never refused for it. Nothing else on the key says the destination is gone."},"external_id":{"type":["string","null"]},"metadata":{"type":"object","additionalProperties":{"type":"string"}},"scopes":{"type":"array","items":{"type":"object","properties":{"scope_type":{"type":"string","enum":["organization","team","project"]},"scope_id":{"type":"string"}},"required":["scope_type","scope_id"]}},"routing_policy_id":{"type":["string","null"]},"routing_mode":{"type":"string","enum":["none","fallback_all","policy"]},"config":{},"revision":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"last_used_at":{"type":["string","null"],"format":"date-time"},"revoked_at":{"type":["string","null"],"format":"date-time"},"expires_at":{"type":["string","null"],"format":"date-time","description":"When the key stops serving, or null for a key that never expires. Requests presented after this moment are refused with `virtual_key_expired`. `status` stays `active` past the date on purpose: the three status values are what clients switch on, and the key stays editable so the date can be extended."}},"required":["id","organization_id","name","description","status","purpose","display_prefix","principal_user_id","trace_project_id","trace_project_archived","external_id","metadata","scopes","routing_policy_id","routing_mode","revision","created_at","updated_at","last_used_at","revoked_at","expires_at"]}},"required":["virtual_key"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]},"patch":{"operationId":"patchApiGatewayV1VirtualKeysById","summary":"Update virtual key","description":"Partial update: send only the fields you want to change. `scopes` replaces the entire visibility set and requires `virtualKeys:manage` at every NEW scope, and does NOT move where the key's traces and costs land: send `trace_project_id` for that, validated the way create validates it; explicit null re-resolves it under the create-time rules rather than clearing it. `config` is deep-merged. `budget` upserts the key's own cap; explicit null archives it.","tags":["Virtual Keys"],"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","properties":{"virtual_key":{"type":"object","properties":{"id":{"type":"string"},"organization_id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"status":{"type":"string","enum":["active","disabled","revoked"]},"purpose":{"type":"string","enum":["user","langy"]},"display_prefix":{"type":"string"},"principal_user_id":{"type":["string","null"]},"trace_project_id":{"type":["string","null"],"description":"The project this key's traces and costs land in, which is the project its spend is attributed to. Not a scope: it grants no access to the key. Decided when the key is written and stored on it, so editing what the key is scoped to never moves it; send `trace_project_id` on an update to move it. Null only on a key created before this was stored, in an organization that had no governance project to fall back to; those keys export no spans until they are given a destination."},"trace_project_archived":{"type":"boolean","description":"True when the project in `trace_project_id` has been deleted. The key goes on sending its traces there, so the data stays whole and reappears if the project is restored, and traffic is never refused for it. Nothing else on the key says the destination is gone."},"external_id":{"type":["string","null"]},"metadata":{"type":"object","additionalProperties":{"type":"string"}},"scopes":{"type":"array","items":{"type":"object","properties":{"scope_type":{"type":"string","enum":["organization","team","project"]},"scope_id":{"type":"string"}},"required":["scope_type","scope_id"]}},"routing_policy_id":{"type":["string","null"]},"routing_mode":{"type":"string","enum":["none","fallback_all","policy"]},"config":{},"revision":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"last_used_at":{"type":["string","null"],"format":"date-time"},"revoked_at":{"type":["string","null"],"format":"date-time"},"expires_at":{"type":["string","null"],"format":"date-time","description":"When the key stops serving, or null for a key that never expires. Requests presented after this moment are refused with `virtual_key_expired`. `status` stays `active` past the date on purpose: the three status values are what clients switch on, and the key stays editable so the date can be extended."}},"required":["id","organization_id","name","description","status","purpose","display_prefix","principal_user_id","trace_project_id","trace_project_archived","external_id","metadata","scopes","routing_policy_id","routing_mode","revision","created_at","updated_at","last_used_at","revoked_at","expires_at"]}},"required":["virtual_key"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":128},"description":{"type":["string","null"]},"scopes":{"type":"array","items":{"type":"object","properties":{"scope_type":{"type":"string","enum":["organization","team","project"]},"scope_id":{"type":"string","minLength":1}},"required":["scope_type","scope_id"]},"minItems":1},"trace_project_id":{"type":["string","null"],"description":"Where the key's traces and costs land. Omit it and the destination stays exactly where it is, scope edits included. A value moves it, validated the way create validates it. Explicit null does not clear it: it asks for the destination to be worked out again from what the key is now, under the same rules create uses. It lands on the key's single project scope when exactly one names a live project, and otherwise on the organization's oldest live governance project when there are no other live projects to choose from. An organization with live projects that could have been named refuses with `gateway_trace_project_ambiguous`, and one with no governance project to fall back on refuses with `trace_project_required`."},"routing_policy_id":{"type":["string","null"]},"routing_mode":{"type":"string","enum":["none","fallback_all","policy"]},"expires_at":{"type":["string","null"],"description":"When the key stops serving. Omit it and the stored date stays where it is; null clears it, so the key never expires; a date moves it. A key whose date has already passed accepts this edit like any other, which is how an expired key is put back in service without minting a new secret. A date in the past is refused with `virtual_key_expiry_in_past`."},"budget":{"type":["object","null"],"properties":{"limit_usd":{"anyOf":[{"type":"number","exclusiveMinimum":0},{"type":"string","pattern":"^\\d+(\\.\\d+)?$"}]},"window":{"type":"string","enum":["day","week","month"]},"on_breach":{"type":"string","enum":["block","warn"]},"name":{"type":"string","minLength":1,"maxLength":128}},"required":["limit_usd","window"]},"config":{"type":"object","properties":{"modelsAllowed":{"type":["array","null"],"items":{"type":"string"},"default":null},"providersAllowed":{"type":["array","null"],"items":{"type":"string"},"default":null},"cache":{"type":"object","properties":{"mode":{"type":"string","enum":["respect","force","disable"],"default":"respect"},"ttlS":{"type":"integer","minimum":0,"default":3600}},"default":{"mode":"respect","ttlS":3600}},"fallback":{"type":"object","properties":{"maxAttempts":{"type":"integer","exclusiveMinimum":0,"default":3}},"default":{"maxAttempts":3}},"guardrailAttachments":{"type":"array","items":{"type":"object","properties":{"direction":{"type":"string","enum":["pre","post","stream_chunk"]},"guardrailIds":{"type":"array","items":{"type":"string"},"default":[]}},"required":["direction"]},"default":[]},"rateLimits":{"type":"object","properties":{"rpm":{"type":["integer","null"],"default":null},"tpm":{"type":["integer","null"],"default":null},"rpd":{"type":["integer","null"],"default":null}},"default":{"rpm":null,"tpm":null,"rpd":null}},"realtime":{"type":"object","properties":{"maxOpenSessions":{"type":["integer","null"],"exclusiveMinimum":0,"default":null}},"default":{"maxOpenSessions":null}},"metadata":{"type":"object","properties":{"label":{"type":"string"},"tags":{"type":"array","items":{"type":"string"},"default":[]}},"default":{"tags":[]}}}},"external_id":{"type":["string","null"],"minLength":1,"maxLength":128},"metadata":{"type":"object","propertyNames":{"type":"string","minLength":1,"maxLength":64},"additionalProperties":{"type":"string","maxLength":500}}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]}},"/api/gateway/v1/virtual-keys/{id}/spend":{"get":{"operationId":"getApiGatewayV1VirtualKeysByIdSpend","summary":"Read a virtual key's spend","description":"Aggregate spend and request count for one key over a window given in epoch milliseconds (default: current UTC calendar month). Reads the cost path (`trace_summaries`), the same source the dashboard's key list and Usage tab read, so this number, the UI column, and the Usage page agree by construction. Returns 412 `spend_source_unavailable` on deploys without a ClickHouse spend source rather than a $0.00 that cannot be told apart from a zero-spend key.","tags":["Virtual Keys"],"responses":{"200":{"description":"Spend summary for the key","content":{"application/json":{"schema":{"type":"object","properties":{"virtual_key_id":{"type":"string"},"spent_usd":{"type":"string","description":"Spend over the window, summed from the cost path. Decimal string, up to 9 fractional digits, trailing zeros trimmed, never exponent notation."},"requests":{"type":"integer"},"window":{"type":"object","properties":{"from":{"type":"integer"},"to":{"type":"integer"}},"required":["from","to"]}},"required":["virtual_key_id","spent_usd","requests","window"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"412":{"description":"No spend source on this deployment","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"parameters":[{"in":"query","name":"from","schema":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},{"in":"query","name":"to","schema":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]}},"/api/gateway/v1/virtual-keys/{id}/rotate":{"post":{"operationId":"postApiGatewayV1VirtualKeysByIdRotate","summary":"Rotate virtual key secret","description":"Mints a fresh secret for an existing VK. The old secret remains valid for 24h (grace window) so in-flight clients can roll over.","tags":["Virtual Keys"],"responses":{"200":{"description":"Rotated","content":{"application/json":{"schema":{"type":"object","properties":{"virtual_key":{"type":"object","properties":{"id":{"type":"string"},"organization_id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"status":{"type":"string","enum":["active","disabled","revoked"]},"purpose":{"type":"string","enum":["user","langy"]},"display_prefix":{"type":"string"},"principal_user_id":{"type":["string","null"]},"trace_project_id":{"type":["string","null"],"description":"The project this key's traces and costs land in, which is the project its spend is attributed to. Not a scope: it grants no access to the key. Decided when the key is written and stored on it, so editing what the key is scoped to never moves it; send `trace_project_id` on an update to move it. Null only on a key created before this was stored, in an organization that had no governance project to fall back to; those keys export no spans until they are given a destination."},"trace_project_archived":{"type":"boolean","description":"True when the project in `trace_project_id` has been deleted. The key goes on sending its traces there, so the data stays whole and reappears if the project is restored, and traffic is never refused for it. Nothing else on the key says the destination is gone."},"external_id":{"type":["string","null"]},"metadata":{"type":"object","additionalProperties":{"type":"string"}},"scopes":{"type":"array","items":{"type":"object","properties":{"scope_type":{"type":"string","enum":["organization","team","project"]},"scope_id":{"type":"string"}},"required":["scope_type","scope_id"]}},"routing_policy_id":{"type":["string","null"]},"routing_mode":{"type":"string","enum":["none","fallback_all","policy"]},"config":{},"revision":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"last_used_at":{"type":["string","null"],"format":"date-time"},"revoked_at":{"type":["string","null"],"format":"date-time"},"expires_at":{"type":["string","null"],"format":"date-time","description":"When the key stops serving, or null for a key that never expires. Requests presented after this moment are refused with `virtual_key_expired`. `status` stays `active` past the date on purpose: the three status values are what clients switch on, and the key stays editable so the date can be extended."}},"required":["id","organization_id","name","description","status","purpose","display_prefix","principal_user_id","trace_project_id","trace_project_archived","external_id","metadata","scopes","routing_policy_id","routing_mode","revision","created_at","updated_at","last_used_at","revoked_at","expires_at"]},"secret":{"type":"string"}},"required":["virtual_key","secret"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]}},"/api/gateway/v1/virtual-keys/{id}/disable":{"post":{"operationId":"postApiGatewayV1VirtualKeysByIdDisable","summary":"Disable virtual key","requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string","maxLength":500,"description":"Operator note, audit-logged and shown in the key's detail view."}}}}}},"description":"Reversible stop: requests on the key are rejected with the distinct `virtual_key_disabled` error until it is enabled again. Budgets, scopes, key material, and any rotation grace stay intact. The change propagates through the gateway's change-event feed. Idempotent.","tags":["Virtual Keys"],"responses":{"200":{"description":"Disabled","content":{"application/json":{"schema":{"type":"object","properties":{"virtual_key":{"type":"object","properties":{"id":{"type":"string"},"organization_id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"status":{"type":"string","enum":["active","disabled","revoked"]},"purpose":{"type":"string","enum":["user","langy"]},"display_prefix":{"type":"string"},"principal_user_id":{"type":["string","null"]},"trace_project_id":{"type":["string","null"],"description":"The project this key's traces and costs land in, which is the project its spend is attributed to. Not a scope: it grants no access to the key. Decided when the key is written and stored on it, so editing what the key is scoped to never moves it; send `trace_project_id` on an update to move it. Null only on a key created before this was stored, in an organization that had no governance project to fall back to; those keys export no spans until they are given a destination."},"trace_project_archived":{"type":"boolean","description":"True when the project in `trace_project_id` has been deleted. The key goes on sending its traces there, so the data stays whole and reappears if the project is restored, and traffic is never refused for it. Nothing else on the key says the destination is gone."},"external_id":{"type":["string","null"]},"metadata":{"type":"object","additionalProperties":{"type":"string"}},"scopes":{"type":"array","items":{"type":"object","properties":{"scope_type":{"type":"string","enum":["organization","team","project"]},"scope_id":{"type":"string"}},"required":["scope_type","scope_id"]}},"routing_policy_id":{"type":["string","null"]},"routing_mode":{"type":"string","enum":["none","fallback_all","policy"]},"config":{},"revision":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"last_used_at":{"type":["string","null"],"format":"date-time"},"revoked_at":{"type":["string","null"],"format":"date-time"},"expires_at":{"type":["string","null"],"format":"date-time","description":"When the key stops serving, or null for a key that never expires. Requests presented after this moment are refused with `virtual_key_expired`. `status` stays `active` past the date on purpose: the three status values are what clients switch on, and the key stays editable so the date can be extended."}},"required":["id","organization_id","name","description","status","purpose","display_prefix","principal_user_id","trace_project_id","trace_project_archived","external_id","metadata","scopes","routing_policy_id","routing_mode","revision","created_at","updated_at","last_used_at","revoked_at","expires_at"]}},"required":["virtual_key"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]}},"/api/gateway/v1/virtual-keys/{id}/enable":{"post":{"operationId":"postApiGatewayV1VirtualKeysByIdEnable","summary":"Enable virtual key","description":"Reverses disable: the key returns to `active` exactly as it was, including any rotation grace that was running. Idempotent.","tags":["Virtual Keys"],"responses":{"200":{"description":"Enabled","content":{"application/json":{"schema":{"type":"object","properties":{"virtual_key":{"type":"object","properties":{"id":{"type":"string"},"organization_id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"status":{"type":"string","enum":["active","disabled","revoked"]},"purpose":{"type":"string","enum":["user","langy"]},"display_prefix":{"type":"string"},"principal_user_id":{"type":["string","null"]},"trace_project_id":{"type":["string","null"],"description":"The project this key's traces and costs land in, which is the project its spend is attributed to. Not a scope: it grants no access to the key. Decided when the key is written and stored on it, so editing what the key is scoped to never moves it; send `trace_project_id` on an update to move it. Null only on a key created before this was stored, in an organization that had no governance project to fall back to; those keys export no spans until they are given a destination."},"trace_project_archived":{"type":"boolean","description":"True when the project in `trace_project_id` has been deleted. The key goes on sending its traces there, so the data stays whole and reappears if the project is restored, and traffic is never refused for it. Nothing else on the key says the destination is gone."},"external_id":{"type":["string","null"]},"metadata":{"type":"object","additionalProperties":{"type":"string"}},"scopes":{"type":"array","items":{"type":"object","properties":{"scope_type":{"type":"string","enum":["organization","team","project"]},"scope_id":{"type":"string"}},"required":["scope_type","scope_id"]}},"routing_policy_id":{"type":["string","null"]},"routing_mode":{"type":"string","enum":["none","fallback_all","policy"]},"config":{},"revision":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"last_used_at":{"type":["string","null"],"format":"date-time"},"revoked_at":{"type":["string","null"],"format":"date-time"},"expires_at":{"type":["string","null"],"format":"date-time","description":"When the key stops serving, or null for a key that never expires. Requests presented after this moment are refused with `virtual_key_expired`. `status` stays `active` past the date on purpose: the three status values are what clients switch on, and the key stays editable so the date can be extended."}},"required":["id","organization_id","name","description","status","purpose","display_prefix","principal_user_id","trace_project_id","trace_project_archived","external_id","metadata","scopes","routing_policy_id","routing_mode","revision","created_at","updated_at","last_used_at","revoked_at","expires_at"]}},"required":["virtual_key"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]}},"/api/gateway/v1/virtual-keys/{id}/revoke":{"post":{"operationId":"postApiGatewayV1VirtualKeysByIdRevoke","summary":"Revoke virtual key","description":"Marks the virtual key as revoked and archives its own budgets. Clients using it start receiving 401 within ~60s (the gateway's change-event long-poll period). Idempotent.","tags":["Virtual Keys"],"responses":{"200":{"description":"Revoked","content":{"application/json":{"schema":{"type":"object","properties":{"virtual_key":{"type":"object","properties":{"id":{"type":"string"},"organization_id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"status":{"type":"string","enum":["active","disabled","revoked"]},"purpose":{"type":"string","enum":["user","langy"]},"display_prefix":{"type":"string"},"principal_user_id":{"type":["string","null"]},"trace_project_id":{"type":["string","null"],"description":"The project this key's traces and costs land in, which is the project its spend is attributed to. Not a scope: it grants no access to the key. Decided when the key is written and stored on it, so editing what the key is scoped to never moves it; send `trace_project_id` on an update to move it. Null only on a key created before this was stored, in an organization that had no governance project to fall back to; those keys export no spans until they are given a destination."},"trace_project_archived":{"type":"boolean","description":"True when the project in `trace_project_id` has been deleted. The key goes on sending its traces there, so the data stays whole and reappears if the project is restored, and traffic is never refused for it. Nothing else on the key says the destination is gone."},"external_id":{"type":["string","null"]},"metadata":{"type":"object","additionalProperties":{"type":"string"}},"scopes":{"type":"array","items":{"type":"object","properties":{"scope_type":{"type":"string","enum":["organization","team","project"]},"scope_id":{"type":"string"}},"required":["scope_type","scope_id"]}},"routing_policy_id":{"type":["string","null"]},"routing_mode":{"type":"string","enum":["none","fallback_all","policy"]},"config":{},"revision":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"last_used_at":{"type":["string","null"],"format":"date-time"},"revoked_at":{"type":["string","null"],"format":"date-time"},"expires_at":{"type":["string","null"],"format":"date-time","description":"When the key stops serving, or null for a key that never expires. Requests presented after this moment are refused with `virtual_key_expired`. `status` stays `active` past the date on purpose: the three status values are what clients switch on, and the key stays editable so the date can be extended."}},"required":["id","organization_id","name","description","status","purpose","display_prefix","principal_user_id","trace_project_id","trace_project_archived","external_id","metadata","scopes","routing_policy_id","routing_mode","revision","created_at","updated_at","last_used_at","revoked_at","expires_at"]}},"required":["virtual_key"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]}},"/api/gateway/v1/providers":{"get":{"operationId":"getApiGatewayV1Providers","summary":"List provider bindings","description":"Lists every gateway-bound model-provider credential for the caller's project, including health and rate-limit settings.","tags":["Providers"],"responses":{"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"410":{"description":"Gone. Gateway provider bindings folded into ModelProvider in iter 110.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"security":[{"project_api_key":[]}]},"post":{"operationId":"postApiGatewayV1Providers","summary":"Bind a model provider to the gateway","description":"Creates a GatewayProviderCredential binding. Reuses the ModelProvider API key already configured in project settings; this only adds gateway-specific settings (rate limits, rotation, fallback priority).","tags":["Providers"],"responses":{"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"410":{"description":"Gone. Gateway provider bindings folded into ModelProvider in iter 110.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"security":[{"project_api_key":[]}]}},"/api/gateway/v1/budgets":{"get":{"operationId":"getApiGatewayV1Budgets","summary":"List budgets","description":"Returns the non-archived budgets in the caller's organization across all seven scope types (organization / team / project / virtual_key / principal / group / attributed_user), with live `spent_usd` from the spend ledger. Newest first, paged by cursor: follow `next_cursor` until it comes back null. Filter with `scope_type` (comma-separated), which is applied in the query, so `limit` counts rows returned. `group` rows are per-member allowances: `limit_usd` is what EACH member may spend, while `spent_usd` is the group's summed spend, and `member_count` says how many members the allowance currently covers. `attributed_user` rows are per-person templates: `limit_usd` is what EACH end user may spend, `end_users_seen` counts the end users with spend this period, and `end_users_over` how many of them are at or over that limit. A template's own `spent_usd` and `spent_nano_usd` are null because one allowance per person has no single total to report; each person's figure is in `GET /spend-summaries` and the seat buckets. `spend_available: false` means spend could not be totalled at all, and both fields are null for that reason instead, rather than a stale figure a caller could read as real money. Every amount is published twice: `_usd` is the display string, `_nano_usd` is the canonical integer in the same nano-USD unit the spend events carry, so a budget and its spend reconcile without parsing decimals.","tags":["Budgets"],"responses":{"200":{"description":"Budgets for the organization","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"organization_id":{"type":"string"},"scope_type":{"type":"string","enum":["organization","team","project","virtual_key","principal","group","attributed_user"]},"scope_id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"window":{"type":"string","enum":["minute","hour","day","week","month","total","manual"]},"on_breach":{"type":"string","enum":["block","warn"]},"limit_usd":{"type":"string","description":"Display value. Decimal string, up to 9 fractional digits, trailing zeros trimmed, never exponent notation. Use limit_nano_usd for arithmetic."},"limit_nano_usd":{"type":["integer","null"],"description":"Canonical integer amount, nano-USD. Null past the safe integer range, where limit_usd still reads."},"spent_usd":{"type":["string","null"],"description":"Display value, null when spend_available is false. Decimal string, up to 9 fractional digits, trailing zeros trimmed, never exponent notation. Use spent_nano_usd for arithmetic."},"spent_nano_usd":{"type":["integer","null"],"description":"Canonical integer spend, nano-USD. Null when spend is unavailable. Derived from the same integer as spent_usd, so the pair always agrees."},"timezone":{"type":["string","null"]},"provider_key":{"type":["string","null"]},"external_id":{"type":["string","null"]},"metadata":{"type":"object","additionalProperties":{"type":"string"}},"current_period_started_at":{"type":"string","description":"Start of the period `spent_usd` covers, computed at read time. For an anchored budget this is its own cycle's start, not the calendar period's."},"resets_at":{"type":"string","description":"When the current period gives way to the next. Far-future for total and manual windows, which do not roll on their own."},"cycle_anchor_at":{"type":["string","null"],"description":"The instant this budget's cycle is phased to. Null means no anchor: a calendar-aligned cyclic window, or one of the two windows that do not cycle (total, manual)."},"last_reset_at":{"type":["string","null"]},"archived_at":{"type":["string","null"]},"created_at":{"type":"string"},"member_count":{"type":"integer"},"end_users_seen":{"type":"integer"},"end_users_over":{"type":"integer"},"scope_reach":{"type":"string","enum":["reachable","unreachable"],"description":"Whether any active key in the organization can produce traffic this budget matches. `unreachable` means it will never accrue and never block as configured: scope a key to its target, or move the budget where the keys already run. This is the only field that tells a budget nothing can reach apart from one that simply has not been breached."}},"required":["id","organization_id","scope_type","scope_id","name","description","window","on_breach","limit_usd","limit_nano_usd","spent_usd","spent_nano_usd","timezone","provider_key","external_id","metadata","current_period_started_at","resets_at","cycle_anchor_at","last_reset_at","archived_at","created_at"]}},"spend_available":{"type":"boolean"},"next_cursor":{"type":["string","null"],"description":"Pass back as `cursor` for the next page. Null means the walk is exhausted; a full page does NOT mean there is more."}},"required":["data","spend_available","next_cursor"]}}}},"400":{"description":"Invalid scope_type filter","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"parameters":[{"in":"query","name":"cursor","schema":{"type":"string","maxLength":500}},{"in":"query","name":"limit","schema":{"type":"integer","exclusiveMinimum":0,"maximum":200,"default":50}},{"in":"query","name":"scope_type","schema":{"type":"string"},"description":"Comma-separated subset of the scope types, lowercase, e.g. `virtual_key,principal`."},{"in":"query","name":"external_id","schema":{"type":"string","maxLength":128},"description":"Exact match on the resource's `external_id`."}],"security":[{"project_api_key":[]}]},"post":{"operationId":"postApiGatewayV1Budgets","summary":"Create budget","description":"Creates an organization-owned budget. The scope discriminates which resource the budget covers, across all seven scope types (organization / team / project / virtual_key / principal / group / attributed_user). `group` budgets are per-member allowances and `attributed_user` budgets are per-end-user templates; both require a deployment with the ClickHouse spend ledger (`group_budget_requires_clickhouse` otherwise). `provider_key` optionally pins the budget to one model provider. `cycle_anchor_at` optionally phases the window off a chosen instant instead of the calendar, for budgets that have to line up with a billing date. A `team`, `project` or `group` budget that none of the organization's active keys can produce traffic for is refused with `gateway_budget_scope_unreachable`, since it would never spend and never block; send `allow_unreachable` to keep it anyway, and note that an organization with no active keys is never refused. Send `Idempotency-Key` to make a retry safe.","tags":["Budgets"],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"A caller-chosen key, 8 to 255 characters, that makes this create safe to retry. The first request to use a key runs normally and its response is stored for 24 hours. A later request with the same key and the same body is not executed again: it returns the stored response, marked with `X-Idempotent-Replay: true`. The same key with a different body is refused 409 `idempotency_error`, as is a retry sent while the original is still running. Only successful responses are stored, so a create that failed can simply be retried with the same key.","schema":{"type":"string","minLength":8,"maxLength":255}}],"responses":{"201":{"description":"Budget created","headers":{"X-Idempotent-Replay":{"description":"Present and `true` only when this body came from a stored response rather than a fresh execution. Absent on the first use of a key, and on every request that carries no key.","schema":{"type":"string","enum":["true"]}}},"content":{"application/json":{"schema":{"type":"object","properties":{"budget":{"type":"object","properties":{"id":{"type":"string"},"organization_id":{"type":"string"},"scope_type":{"type":"string","enum":["organization","team","project","virtual_key","principal","group","attributed_user"]},"scope_id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"window":{"type":"string","enum":["minute","hour","day","week","month","total","manual"]},"on_breach":{"type":"string","enum":["block","warn"]},"limit_usd":{"type":"string","description":"Display value. Decimal string, up to 9 fractional digits, trailing zeros trimmed, never exponent notation. Use limit_nano_usd for arithmetic."},"limit_nano_usd":{"type":["integer","null"],"description":"Canonical integer amount, nano-USD. Null past the safe integer range, where limit_usd still reads."},"spent_usd":{"type":["string","null"],"description":"Display value, null when spend_available is false. Decimal string, up to 9 fractional digits, trailing zeros trimmed, never exponent notation. Use spent_nano_usd for arithmetic."},"spent_nano_usd":{"type":["integer","null"],"description":"Canonical integer spend, nano-USD. Null when spend is unavailable. Derived from the same integer as spent_usd, so the pair always agrees."},"timezone":{"type":["string","null"]},"provider_key":{"type":["string","null"]},"external_id":{"type":["string","null"]},"metadata":{"type":"object","additionalProperties":{"type":"string"}},"current_period_started_at":{"type":"string","description":"Start of the period `spent_usd` covers, computed at read time. For an anchored budget this is its own cycle's start, not the calendar period's."},"resets_at":{"type":"string","description":"When the current period gives way to the next. Far-future for total and manual windows, which do not roll on their own."},"cycle_anchor_at":{"type":["string","null"],"description":"The instant this budget's cycle is phased to. Null means no anchor: a calendar-aligned cyclic window, or one of the two windows that do not cycle (total, manual)."},"last_reset_at":{"type":["string","null"]},"archived_at":{"type":["string","null"]},"created_at":{"type":"string"},"member_count":{"type":"integer"},"end_users_seen":{"type":"integer"},"end_users_over":{"type":"integer"},"scope_reach":{"type":"string","enum":["reachable","unreachable"],"description":"Whether any active key in the organization can produce traffic this budget matches. `unreachable` means it will never accrue and never block as configured: scope a key to its target, or move the budget where the keys already run. This is the only field that tells a budget nothing can reach apart from one that simply has not been breached."}},"required":["id","organization_id","scope_type","scope_id","name","description","window","on_breach","limit_usd","limit_nano_usd","spent_usd","spent_nano_usd","timezone","provider_key","external_id","metadata","current_period_started_at","resets_at","cycle_anchor_at","last_reset_at","archived_at","created_at"]}},"required":["budget"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"scope":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"organization"},"organization_id":{"type":"string"}},"required":["kind","organization_id"]},{"type":"object","properties":{"kind":{"type":"string","const":"team"},"team_id":{"type":"string"}},"required":["kind","team_id"]},{"type":"object","properties":{"kind":{"type":"string","const":"project"},"project_id":{"type":"string"}},"required":["kind","project_id"]},{"type":"object","properties":{"kind":{"type":"string","const":"virtual_key"},"virtual_key_id":{"type":"string"}},"required":["kind","virtual_key_id"]},{"type":"object","properties":{"kind":{"type":"string","const":"principal"},"principal_user_id":{"type":"string"}},"required":["kind","principal_user_id"]},{"type":"object","properties":{"kind":{"type":"string","const":"group"},"group_id":{"type":"string"}},"required":["kind","group_id"]},{"type":"object","properties":{"kind":{"type":"string","const":"attributed_user"},"anchor_virtual_key_id":{"type":"string"},"anchor_project_id":{"type":"string"}},"required":["kind"]}]},"name":{"type":"string","minLength":1,"maxLength":128},"description":{"type":"string"},"window":{"type":"string","enum":["minute","hour","day","week","month","total","manual"]},"limit_usd":{"anyOf":[{"type":"number","exclusiveMinimum":0},{"type":"string","pattern":"^\\d+(\\.\\d+)?$"}]},"on_breach":{"type":"string","enum":["block","warn"]},"timezone":{"type":["string","null"]},"provider_key":{"type":["string","null"]},"external_id":{"type":["string","null"],"minLength":1,"maxLength":128},"metadata":{"type":"object","propertyNames":{"type":"string","minLength":1,"maxLength":64},"additionalProperties":{"type":"string","maxLength":500}},"cycle_anchor_at":{"type":"string","format":"date-time","description":"Phases the budget's cycle off this instant instead of the calendar, so a `month` budget anchored 2026-01-17T09:00:00Z starts a fresh period every 17th at 09:00 UTC. Omit for calendar alignment, which is the default and unchanged behaviour. A month cycle anchored past the 28th clamps into shorter months and springs back: anchored on the 31st gives Feb 28, then Mar 31. Immutable after create, since moving it would redraw periods the budget has already reported and enforced on. Rejected with `gateway_budget_cycle_anchor_invalid` on `total` and `manual`, which do not cycle."},"allow_unreachable":{"type":"boolean","description":"Keeps a `team`, `project` or `group` budget that no active key can produce traffic for, which is otherwise refused with `gateway_budget_scope_unreachable`. Send it to provision ahead of the keys that will use the budget. An organization with no active keys is never refused, so this is not needed during first setup."}},"required":["scope","name","window","limit_usd"]}}}},"security":[{"project_api_key":[]}]}},"/api/gateway/v1/budgets/{id}":{"get":{"operationId":"getApiGatewayV1BudgetsById","summary":"Get budget","description":"One budget, in exactly the row shape `GET /budgets` returns, including the live spend enrichment and the per-person `end_users_seen` / `end_users_over` standing on attributed-user templates. Archived budgets are not returned. `spend_available: false` means spend could not be totalled, and `spent_usd` / `spent_nano_usd` are null rather than a figure that cannot be told apart from zero spend. A per-person template reports null there too, because one allowance per person has no single total; each person's figure is in `GET /spend-summaries` and the seat buckets.","tags":["Budgets"],"responses":{"200":{"description":"The budget","content":{"application/json":{"schema":{"type":"object","properties":{"budget":{"type":"object","properties":{"id":{"type":"string"},"organization_id":{"type":"string"},"scope_type":{"type":"string","enum":["organization","team","project","virtual_key","principal","group","attributed_user"]},"scope_id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"window":{"type":"string","enum":["minute","hour","day","week","month","total","manual"]},"on_breach":{"type":"string","enum":["block","warn"]},"limit_usd":{"type":"string","description":"Display value. Decimal string, up to 9 fractional digits, trailing zeros trimmed, never exponent notation. Use limit_nano_usd for arithmetic."},"limit_nano_usd":{"type":["integer","null"],"description":"Canonical integer amount, nano-USD. Null past the safe integer range, where limit_usd still reads."},"spent_usd":{"type":["string","null"],"description":"Display value, null when spend_available is false. Decimal string, up to 9 fractional digits, trailing zeros trimmed, never exponent notation. Use spent_nano_usd for arithmetic."},"spent_nano_usd":{"type":["integer","null"],"description":"Canonical integer spend, nano-USD. Null when spend is unavailable. Derived from the same integer as spent_usd, so the pair always agrees."},"timezone":{"type":["string","null"]},"provider_key":{"type":["string","null"]},"external_id":{"type":["string","null"]},"metadata":{"type":"object","additionalProperties":{"type":"string"}},"current_period_started_at":{"type":"string","description":"Start of the period `spent_usd` covers, computed at read time. For an anchored budget this is its own cycle's start, not the calendar period's."},"resets_at":{"type":"string","description":"When the current period gives way to the next. Far-future for total and manual windows, which do not roll on their own."},"cycle_anchor_at":{"type":["string","null"],"description":"The instant this budget's cycle is phased to. Null means no anchor: a calendar-aligned cyclic window, or one of the two windows that do not cycle (total, manual)."},"last_reset_at":{"type":["string","null"]},"archived_at":{"type":["string","null"]},"created_at":{"type":"string"},"member_count":{"type":"integer"},"end_users_seen":{"type":"integer"},"end_users_over":{"type":"integer"},"scope_reach":{"type":"string","enum":["reachable","unreachable"],"description":"Whether any active key in the organization can produce traffic this budget matches. `unreachable` means it will never accrue and never block as configured: scope a key to its target, or move the budget where the keys already run. This is the only field that tells a budget nothing can reach apart from one that simply has not been breached."}},"required":["id","organization_id","scope_type","scope_id","name","description","window","on_breach","limit_usd","limit_nano_usd","spent_usd","spent_nano_usd","timezone","provider_key","external_id","metadata","current_period_started_at","resets_at","cycle_anchor_at","last_reset_at","archived_at","created_at"]},"spend_available":{"type":"boolean"}},"required":["budget","spend_available"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]},"patch":{"operationId":"patchApiGatewayV1BudgetsById","summary":"Update budget","description":"Partial update. Scope, window and cycle_anchor_at are immutable after create. Use explicit null to clear timezone / description.","tags":["Budgets"],"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","properties":{"budget":{"type":"object","properties":{"id":{"type":"string"},"organization_id":{"type":"string"},"scope_type":{"type":"string","enum":["organization","team","project","virtual_key","principal","group","attributed_user"]},"scope_id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"window":{"type":"string","enum":["minute","hour","day","week","month","total","manual"]},"on_breach":{"type":"string","enum":["block","warn"]},"limit_usd":{"type":"string","description":"Display value. Decimal string, up to 9 fractional digits, trailing zeros trimmed, never exponent notation. Use limit_nano_usd for arithmetic."},"limit_nano_usd":{"type":["integer","null"],"description":"Canonical integer amount, nano-USD. Null past the safe integer range, where limit_usd still reads."},"spent_usd":{"type":["string","null"],"description":"Display value, null when spend_available is false. Decimal string, up to 9 fractional digits, trailing zeros trimmed, never exponent notation. Use spent_nano_usd for arithmetic."},"spent_nano_usd":{"type":["integer","null"],"description":"Canonical integer spend, nano-USD. Null when spend is unavailable. Derived from the same integer as spent_usd, so the pair always agrees."},"timezone":{"type":["string","null"]},"provider_key":{"type":["string","null"]},"external_id":{"type":["string","null"]},"metadata":{"type":"object","additionalProperties":{"type":"string"}},"current_period_started_at":{"type":"string","description":"Start of the period `spent_usd` covers, computed at read time. For an anchored budget this is its own cycle's start, not the calendar period's."},"resets_at":{"type":"string","description":"When the current period gives way to the next. Far-future for total and manual windows, which do not roll on their own."},"cycle_anchor_at":{"type":["string","null"],"description":"The instant this budget's cycle is phased to. Null means no anchor: a calendar-aligned cyclic window, or one of the two windows that do not cycle (total, manual)."},"last_reset_at":{"type":["string","null"]},"archived_at":{"type":["string","null"]},"created_at":{"type":"string"},"member_count":{"type":"integer"},"end_users_seen":{"type":"integer"},"end_users_over":{"type":"integer"},"scope_reach":{"type":"string","enum":["reachable","unreachable"],"description":"Whether any active key in the organization can produce traffic this budget matches. `unreachable` means it will never accrue and never block as configured: scope a key to its target, or move the budget where the keys already run. This is the only field that tells a budget nothing can reach apart from one that simply has not been breached."}},"required":["id","organization_id","scope_type","scope_id","name","description","window","on_breach","limit_usd","limit_nano_usd","spent_usd","spent_nano_usd","timezone","provider_key","external_id","metadata","current_period_started_at","resets_at","cycle_anchor_at","last_reset_at","archived_at","created_at"]}},"required":["budget"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":128},"description":{"type":["string","null"]},"limit_usd":{"anyOf":[{"type":"number","exclusiveMinimum":0},{"type":"string","pattern":"^\\d+(\\.\\d+)?$"}]},"on_breach":{"type":"string","enum":["block","warn"]},"timezone":{"type":["string","null"]},"external_id":{"type":["string","null"],"minLength":1,"maxLength":128},"metadata":{"type":"object","propertyNames":{"type":"string","minLength":1,"maxLength":64},"additionalProperties":{"type":"string","maxLength":500}}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]},"delete":{"operationId":"deleteApiGatewayV1BudgetsById","summary":"Archive budget","description":"Soft-delete: the row is marked archived and no longer counted by the budget engine. Historical ledger entries are retained.","tags":["Budgets"],"responses":{"200":{"description":"Archived","content":{"application/json":{"schema":{"type":"object","properties":{"budget":{"type":"object","properties":{"id":{"type":"string"},"organization_id":{"type":"string"},"scope_type":{"type":"string","enum":["organization","team","project","virtual_key","principal","group","attributed_user"]},"scope_id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"window":{"type":"string","enum":["minute","hour","day","week","month","total","manual"]},"on_breach":{"type":"string","enum":["block","warn"]},"limit_usd":{"type":"string","description":"Display value. Decimal string, up to 9 fractional digits, trailing zeros trimmed, never exponent notation. Use limit_nano_usd for arithmetic."},"limit_nano_usd":{"type":["integer","null"],"description":"Canonical integer amount, nano-USD. Null past the safe integer range, where limit_usd still reads."},"spent_usd":{"type":["string","null"],"description":"Display value, null when spend_available is false. Decimal string, up to 9 fractional digits, trailing zeros trimmed, never exponent notation. Use spent_nano_usd for arithmetic."},"spent_nano_usd":{"type":["integer","null"],"description":"Canonical integer spend, nano-USD. Null when spend is unavailable. Derived from the same integer as spent_usd, so the pair always agrees."},"timezone":{"type":["string","null"]},"provider_key":{"type":["string","null"]},"external_id":{"type":["string","null"]},"metadata":{"type":"object","additionalProperties":{"type":"string"}},"current_period_started_at":{"type":"string","description":"Start of the period `spent_usd` covers, computed at read time. For an anchored budget this is its own cycle's start, not the calendar period's."},"resets_at":{"type":"string","description":"When the current period gives way to the next. Far-future for total and manual windows, which do not roll on their own."},"cycle_anchor_at":{"type":["string","null"],"description":"The instant this budget's cycle is phased to. Null means no anchor: a calendar-aligned cyclic window, or one of the two windows that do not cycle (total, manual)."},"last_reset_at":{"type":["string","null"]},"archived_at":{"type":["string","null"]},"created_at":{"type":"string"},"member_count":{"type":"integer"},"end_users_seen":{"type":"integer"},"end_users_over":{"type":"integer"},"scope_reach":{"type":"string","enum":["reachable","unreachable"],"description":"Whether any active key in the organization can produce traffic this budget matches. `unreachable` means it will never accrue and never block as configured: scope a key to its target, or move the budget where the keys already run. This is the only field that tells a budget nothing can reach apart from one that simply has not been breached."}},"required":["id","organization_id","scope_type","scope_id","name","description","window","on_breach","limit_usd","limit_nano_usd","spent_usd","spent_nano_usd","timezone","provider_key","external_id","metadata","current_period_started_at","resets_at","cycle_anchor_at","last_reset_at","archived_at","created_at"]}},"required":["budget"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]}},"/api/gateway/v1/budgets/{id}/reset":{"post":{"operationId":"postApiGatewayV1BudgetsByIdReset","summary":"Reset budget period","requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string","maxLength":500,"description":"Free-text operator note, audit-logged with the reset."}}}}}},"description":"Moves the budget's period boundary to now and recomputes the next reset; recorded spend is NEVER mutated (the ledger and every emitted billing event are immutable, so reconciliation is unaffected). On calendar windows this truncates the running period and the next boundary stays calendar; on `manual` windows the new period stays open until the next reset. For attributed-user templates, `end_user_id` resets ONE end-user bucket's boundary and leaves the template period untouched.","tags":["Budgets"],"responses":{"200":{"description":"Reset","content":{"application/json":{"schema":{"type":"object","properties":{"budget":{"type":"object","properties":{"id":{"type":"string"},"organization_id":{"type":"string"},"scope_type":{"type":"string","enum":["organization","team","project","virtual_key","principal","group","attributed_user"]},"scope_id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"window":{"type":"string","enum":["minute","hour","day","week","month","total","manual"]},"on_breach":{"type":"string","enum":["block","warn"]},"limit_usd":{"type":"string","description":"Display value. Decimal string, up to 9 fractional digits, trailing zeros trimmed, never exponent notation. Use limit_nano_usd for arithmetic."},"limit_nano_usd":{"type":["integer","null"],"description":"Canonical integer amount, nano-USD. Null past the safe integer range, where limit_usd still reads."},"spent_usd":{"type":["string","null"],"description":"Display value, null when spend_available is false. Decimal string, up to 9 fractional digits, trailing zeros trimmed, never exponent notation. Use spent_nano_usd for arithmetic."},"spent_nano_usd":{"type":["integer","null"],"description":"Canonical integer spend, nano-USD. Null when spend is unavailable. Derived from the same integer as spent_usd, so the pair always agrees."},"timezone":{"type":["string","null"]},"provider_key":{"type":["string","null"]},"external_id":{"type":["string","null"]},"metadata":{"type":"object","additionalProperties":{"type":"string"}},"current_period_started_at":{"type":"string","description":"Start of the period `spent_usd` covers, computed at read time. For an anchored budget this is its own cycle's start, not the calendar period's."},"resets_at":{"type":"string","description":"When the current period gives way to the next. Far-future for total and manual windows, which do not roll on their own."},"cycle_anchor_at":{"type":["string","null"],"description":"The instant this budget's cycle is phased to. Null means no anchor: a calendar-aligned cyclic window, or one of the two windows that do not cycle (total, manual)."},"last_reset_at":{"type":["string","null"]},"archived_at":{"type":["string","null"]},"created_at":{"type":"string"},"member_count":{"type":"integer"},"end_users_seen":{"type":"integer"},"end_users_over":{"type":"integer"},"scope_reach":{"type":"string","enum":["reachable","unreachable"],"description":"Whether any active key in the organization can produce traffic this budget matches. `unreachable` means it will never accrue and never block as configured: scope a key to its target, or move the budget where the keys already run. This is the only field that tells a budget nothing can reach apart from one that simply has not been breached."}},"required":["id","organization_id","scope_type","scope_id","name","description","window","on_breach","limit_usd","limit_nano_usd","spent_usd","spent_nano_usd","timezone","provider_key","external_id","metadata","current_period_started_at","resets_at","cycle_anchor_at","last_reset_at","archived_at","created_at"]}},"required":["budget"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"parameters":[{"in":"query","name":"end_user_id","schema":{"type":"string","minLength":1},"description":"Resets ONE end-user bucket on an attributed-user template, leaving the template period untouched."},{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]}},"/api/gateway/v1/providers/{id}":{"patch":{"operationId":"patchApiGatewayV1ProvidersById","summary":"Update provider binding","description":"Partial update of gateway-specific settings (rate limits, rotation, slot, extra headers). The underlying ModelProvider credentials are managed in project settings, not here.","tags":["Providers"],"responses":{"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"410":{"description":"Gone. Gateway provider bindings folded into ModelProvider in iter 110.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]},"delete":{"operationId":"deleteApiGatewayV1ProvidersById","summary":"Disable provider binding","description":"Marks the binding disabled. Requests routing to this slot are skipped (fallback chain continues). Historical ledger rows are retained.","tags":["Providers"],"responses":{"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"410":{"description":"Gone. Gateway provider bindings folded into ModelProvider in iter 110.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]}},"/api/gateway/v1/cache-rules":{"get":{"operationId":"getApiGatewayV1CacheRules","summary":"List cache-control rules","description":"Organization-scoped operator-authored rules, sorted priority descending then oldest first, with archived rules excluded. Paged by cursor: follow `next_cursor` until it comes back null. Matchers and action are returned verbatim as JSON.","tags":["Cache Rules"],"responses":{"200":{"description":"Cache rules for the organisation","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"organization_id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"priority":{"type":"integer"},"enabled":{"type":"boolean"},"matchers":{"type":"object","additionalProperties":{}},"action":{"type":"object","properties":{"mode":{"type":"string","enum":["respect","force","disable"]},"ttl":{"type":"integer"},"salt":{"type":"string"}},"required":["mode"]},"mode_enum":{"type":"string","enum":["respect","force","disable"]},"archived_at":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","organization_id","name","description","priority","enabled","matchers","action","mode_enum","archived_at","created_at","updated_at"]}},"next_cursor":{"type":["string","null"],"description":"Pass back as `cursor` for the next page. Null means the walk is exhausted; a full page does NOT mean there is more."}},"required":["data","next_cursor"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"parameters":[{"in":"query","name":"cursor","schema":{"type":"string","maxLength":500}},{"in":"query","name":"limit","schema":{"type":"integer","exclusiveMinimum":0,"maximum":200,"default":50}}],"security":[{"project_api_key":[]}]},"post":{"operationId":"postApiGatewayV1CacheRules","summary":"Create a cache rule","description":"Matchers are ANDed across non-null fields; at least one matcher is required. Mode is one of respect/force/disable. TTL is clamped to [0, 86400]. Salt is an optional cache-bust tag (max 64 chars). All writes emit a ChangeEvent so the gateway picks up the new rule within 30 s via its /changes long-poll. Send `Idempotency-Key` to make a retry safe.","tags":["Cache Rules"],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"A caller-chosen key, 8 to 255 characters, that makes this create safe to retry. The first request to use a key runs normally and its response is stored for 24 hours. A later request with the same key and the same body is not executed again: it returns the stored response, marked with `X-Idempotent-Replay: true`. The same key with a different body is refused 409 `idempotency_error`, as is a retry sent while the original is still running. Only successful responses are stored, so a create that failed can simply be retried with the same key.","schema":{"type":"string","minLength":8,"maxLength":255}}],"responses":{"201":{"description":"Created","headers":{"X-Idempotent-Replay":{"description":"Present and `true` only when this body came from a stored response rather than a fresh execution. Absent on the first use of a key, and on every request that carries no key.","schema":{"type":"string","enum":["true"]}}},"content":{"application/json":{"schema":{"type":"object","properties":{"cache_rule":{"type":"object","properties":{"id":{"type":"string"},"organization_id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"priority":{"type":"integer"},"enabled":{"type":"boolean"},"matchers":{"type":"object","additionalProperties":{}},"action":{"type":"object","properties":{"mode":{"type":"string","enum":["respect","force","disable"]},"ttl":{"type":"integer"},"salt":{"type":"string"}},"required":["mode"]},"mode_enum":{"type":"string","enum":["respect","force","disable"]},"archived_at":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","organization_id","name","description","priority","enabled","matchers","action","mode_enum","archived_at","created_at","updated_at"]}},"required":["cache_rule"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":128},"description":{"type":["string","null"],"maxLength":512},"priority":{"type":"integer","minimum":0,"maximum":1000},"enabled":{"type":"boolean"},"matchers":{"type":"object","properties":{"vk_id":{"type":"string"},"vk_tags":{"type":"array","items":{"type":"string"}},"vk_prefix":{"type":"string"},"principal_id":{"type":"string"},"model":{"type":"string"},"request_metadata":{"type":"object","additionalProperties":{"type":"string"}}},"additionalProperties":false},"action":{"type":"object","properties":{"mode":{"type":"string","enum":["respect","force","disable"]},"ttl":{"type":"integer","minimum":0,"maximum":86400},"salt":{"type":"string","maxLength":64}},"required":["mode"],"additionalProperties":false}},"required":["name","matchers","action"]}}}},"security":[{"project_api_key":[]}]}},"/api/gateway/v1/cache-rules/{id}":{"get":{"operationId":"getApiGatewayV1CacheRulesById","summary":"Get a cache rule","description":"Returns the rule if it belongs to the caller's organisation; 404 otherwise. Archived rules are NOT returned (use the audit log to inspect removed rules).","tags":["Cache Rules"],"responses":{"200":{"description":"The rule","content":{"application/json":{"schema":{"type":"object","properties":{"cache_rule":{"type":"object","properties":{"id":{"type":"string"},"organization_id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"priority":{"type":"integer"},"enabled":{"type":"boolean"},"matchers":{"type":"object","additionalProperties":{}},"action":{"type":"object","properties":{"mode":{"type":"string","enum":["respect","force","disable"]},"ttl":{"type":"integer"},"salt":{"type":"string"}},"required":["mode"]},"mode_enum":{"type":"string","enum":["respect","force","disable"]},"archived_at":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","organization_id","name","description","priority","enabled","matchers","action","mode_enum","archived_at","created_at","updated_at"]}},"required":["cache_rule"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]},"patch":{"operationId":"patchApiGatewayV1CacheRulesById","summary":"Update a cache rule","description":"Partial update. `matchers` and `action` REPLACE the stored value when provided (not merged field-by-field). Omitting them leaves the stored value untouched. The rule id + organisation are immutable.","tags":["Cache Rules"],"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","properties":{"cache_rule":{"type":"object","properties":{"id":{"type":"string"},"organization_id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"priority":{"type":"integer"},"enabled":{"type":"boolean"},"matchers":{"type":"object","additionalProperties":{}},"action":{"type":"object","properties":{"mode":{"type":"string","enum":["respect","force","disable"]},"ttl":{"type":"integer"},"salt":{"type":"string"}},"required":["mode"]},"mode_enum":{"type":"string","enum":["respect","force","disable"]},"archived_at":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","organization_id","name","description","priority","enabled","matchers","action","mode_enum","archived_at","created_at","updated_at"]}},"required":["cache_rule"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":128},"description":{"type":["string","null"],"maxLength":512},"priority":{"type":"integer","minimum":0,"maximum":1000},"enabled":{"type":"boolean"},"matchers":{"type":"object","properties":{"vk_id":{"type":"string"},"vk_tags":{"type":"array","items":{"type":"string"}},"vk_prefix":{"type":"string"},"principal_id":{"type":"string"},"model":{"type":"string"},"request_metadata":{"type":"object","additionalProperties":{"type":"string"}}},"additionalProperties":false},"action":{"type":"object","properties":{"mode":{"type":"string","enum":["respect","force","disable"]},"ttl":{"type":"integer","minimum":0,"maximum":86400},"salt":{"type":"string","maxLength":64}},"required":["mode"],"additionalProperties":false}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]},"delete":{"operationId":"deleteApiGatewayV1CacheRulesById","summary":"Archive a cache rule","description":"Soft-delete: sets archivedAt. The rule stops matching new requests. Audit log retains before/after snapshots. Returns the archived row.","tags":["Cache Rules"],"responses":{"200":{"description":"Archived","content":{"application/json":{"schema":{"type":"object","properties":{"cache_rule":{"type":"object","properties":{"id":{"type":"string"},"organization_id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"priority":{"type":"integer"},"enabled":{"type":"boolean"},"matchers":{"type":"object","additionalProperties":{}},"action":{"type":"object","properties":{"mode":{"type":"string","enum":["respect","force","disable"]},"ttl":{"type":"integer"},"salt":{"type":"string"}},"required":["mode"]},"mode_enum":{"type":"string","enum":["respect","force","disable"]},"archived_at":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","organization_id","name","description","priority","enabled","matchers","action","mode_enum","archived_at","created_at","updated_at"]}},"required":["cache_rule"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]}},"/api/governance/ingestion-templates":{"get":{"operationId":"getApiGovernanceIngestionTemplates","summary":"List ingestion templates","description":"Returns the union of platform-published default templates and any org-authored templates visible to the caller's organization. Disabled / archived rows are filtered out. `ottl_rules` is empty in this end-user shape; admins use GET /ingestion-templates/admin to read the canonical OTTL.","tags":["Governance / Ingestion Templates"],"responses":{"200":{"description":"Templates visible to the caller","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"source_type":{"type":"string"},"display_name":{"type":"string"},"description":{"type":["string","null"]},"icon_asset":{"type":["string","null"]},"credential_schema":{"type":["string","null"]},"ottl_rules":{"type":"string"},"platform_published":{"type":"boolean"},"enabled":{"type":"boolean"},"organization_id":{"type":["string","null"]}},"required":["id","slug","source_type","display_name","description","icon_asset","credential_schema","ottl_rules","platform_published","enabled","organization_id"]}}},"required":["data"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"security":[{"project_api_key":[]}]},"post":{"operationId":"postApiGovernanceIngestionTemplates","summary":"Create org-authored ingestion template","description":"Creates a brand-new template scoped to the caller's organization. Slug is auto-generated. Platform rows (organizationId IS NULL) are NEVER created via this endpoint — admins customize platform defaults via POST /ingestion-templates/clone instead.","tags":["Governance / Ingestion Templates"],"responses":{"201":{"description":"Template created","content":{"application/json":{"schema":{"type":"object","properties":{"ingestion_template":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"source_type":{"type":"string"},"display_name":{"type":"string"},"description":{"type":["string","null"]},"icon_asset":{"type":["string","null"]},"credential_schema":{"type":["string","null"]},"ottl_rules":{"type":"string"},"platform_published":{"type":"boolean"},"enabled":{"type":"boolean"},"organization_id":{"type":["string","null"]}},"required":["id","slug","source_type","display_name","description","icon_asset","credential_schema","ottl_rules","platform_published","enabled","organization_id"]}},"required":["ingestion_template"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"security":[{"project_api_key":[]}]}},"/api/governance/ingestion-templates/admin":{"get":{"operationId":"getApiGovernanceIngestionTemplatesAdmin","summary":"List ingestion templates (admin shape, includes OTTL)","description":"Same union as the user list but includes the canonical `ottl_rules` source for every row. Used by admin tooling to render the transparency block / authoring drawer.","tags":["Governance / Ingestion Templates"],"responses":{"200":{"description":"Admin templates","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"source_type":{"type":"string"},"display_name":{"type":"string"},"description":{"type":["string","null"]},"icon_asset":{"type":["string","null"]},"credential_schema":{"type":["string","null"]},"ottl_rules":{"type":"string"},"platform_published":{"type":"boolean"},"enabled":{"type":"boolean"},"organization_id":{"type":["string","null"]}},"required":["id","slug","source_type","display_name","description","icon_asset","credential_schema","ottl_rules","platform_published","enabled","organization_id"]}}},"required":["data"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"security":[{"project_api_key":[]}]}},"/api/governance/ingestion-templates/{id}":{"get":{"operationId":"getApiGovernanceIngestionTemplatesById","summary":"Get ingestion template","description":"Single-template lookup by id, scoped to the caller's organization. Cross-org probes collapse to 404 (no enumeration vector).","tags":["Governance / Ingestion Templates"],"responses":{"200":{"description":"Template detail","content":{"application/json":{"schema":{"type":"object","properties":{"ingestion_template":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"source_type":{"type":"string"},"display_name":{"type":"string"},"description":{"type":["string","null"]},"icon_asset":{"type":["string","null"]},"credential_schema":{"type":["string","null"]},"ottl_rules":{"type":"string"},"platform_published":{"type":"boolean"},"enabled":{"type":"boolean"},"organization_id":{"type":["string","null"]}},"required":["id","slug","source_type","display_name","description","icon_asset","credential_schema","ottl_rules","platform_published","enabled","organization_id"]}},"required":["ingestion_template"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]},"delete":{"operationId":"deleteApiGovernanceIngestionTemplatesById","summary":"Soft-archive an org-authored template","description":"Marks the row archived; existing ingestion keys continue to land traces but the row disappears from list views. Platform-published rows reject with 403.","tags":["Governance / Ingestion Templates"],"responses":{"200":{"description":"Archived","content":{"application/json":{"schema":{"type":"object","properties":{"archived":{"type":"boolean","const":true}},"required":["archived"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"403":{"description":"Platform template immutable","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"404":{"description":"Template not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]}},"/api/governance/ingestion-templates/{id}/ottl-rules":{"patch":{"operationId":"patchApiGovernanceIngestionTemplatesByIdOttlRules","summary":"Replace ottl_rules on an org-authored template","description":"Audit-logged with line counts pre/post. Platform-published rows reject with 403. Admins must clone a platform row before editing it.","tags":["Governance / Ingestion Templates"],"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","properties":{"ingestion_template":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"source_type":{"type":"string"},"display_name":{"type":"string"},"description":{"type":["string","null"]},"icon_asset":{"type":["string","null"]},"credential_schema":{"type":["string","null"]},"ottl_rules":{"type":"string"},"platform_published":{"type":"boolean"},"enabled":{"type":"boolean"},"organization_id":{"type":["string","null"]}},"required":["id","slug","source_type","display_name","description","icon_asset","credential_schema","ottl_rules","platform_published","enabled","organization_id"]}},"required":["ingestion_template"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"403":{"description":"Platform template immutable","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"404":{"description":"Template not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]}},"/api/governance/ingestion-templates/clone":{"post":{"operationId":"postApiGovernanceIngestionTemplatesClone","summary":"Clone a platform-published template into the caller's org","description":"Forks the source row's source_type / display_name / OTTL into a fresh org-authored row that the admin can then edit via PATCH /ingestion-templates/:id/ottl-rules.","tags":["Governance / Ingestion Templates"],"responses":{"201":{"description":"Cloned","content":{"application/json":{"schema":{"type":"object","properties":{"ingestion_template":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"source_type":{"type":"string"},"display_name":{"type":"string"},"description":{"type":["string","null"]},"icon_asset":{"type":["string","null"]},"credential_schema":{"type":["string","null"]},"ottl_rules":{"type":"string"},"platform_published":{"type":"boolean"},"enabled":{"type":"boolean"},"organization_id":{"type":["string","null"]}},"required":["id","slug","source_type","display_name","description","icon_asset","credential_schema","ottl_rules","platform_published","enabled","organization_id"]}},"required":["ingestion_template"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Source template not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"security":[{"project_api_key":[]}]}},"/api/graphs":{"get":{"operationId":"getApiGraphs","description":"List all custom graphs, optionally filtered by dashboard","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"graph":{"type":"object","additionalProperties":{}},"filters":{"type":["object","null"],"additionalProperties":{}},"dashboardId":{"type":["string","null"]},"gridColumn":{"type":"number"},"gridRow":{"type":"number"},"colSpan":{"type":"number"},"rowSpan":{"type":"number"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","name","graph","filters","dashboardId","gridColumn","gridRow","colSpan","rowSpan","createdAt","updatedAt"]}}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"parameters":[{"in":"query","name":"dashboardId","schema":{"type":"string"}}],"security":[{"project_api_key":[]}]},"post":{"operationId":"postApiGraphs","description":"Create a custom graph on a dashboard","responses":{"201":{"description":"Graph created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"graph":{"type":"object","additionalProperties":{}},"filters":{"type":["object","null"],"additionalProperties":{}},"dashboardId":{"type":["string","null"]},"gridColumn":{"type":"number"},"gridRow":{"type":"number"},"colSpan":{"type":"number"},"rowSpan":{"type":"number"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","name","graph","filters","dashboardId","gridColumn","gridRow","colSpan","rowSpan","createdAt","updatedAt"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1},"graph":{"type":"object","additionalProperties":{}},"dashboardId":{"type":"string"},"filters":{"type":"object","additionalProperties":{}},"gridColumn":{"type":"number","minimum":0,"maximum":1},"gridRow":{"type":"number","minimum":0},"colSpan":{"type":"number","minimum":1,"maximum":2},"rowSpan":{"type":"number","minimum":1,"maximum":2}},"required":["name","graph"]}}}},"security":[{"project_api_key":[]}]}},"/api/graphs/{id}":{"get":{"operationId":"getApiGraphsById","description":"Get a custom graph by its ID","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"graph":{"type":"object","additionalProperties":{}},"filters":{"type":["object","null"],"additionalProperties":{}},"dashboardId":{"type":["string","null"]},"gridColumn":{"type":"number"},"gridRow":{"type":"number"},"colSpan":{"type":"number"},"rowSpan":{"type":"number"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","name","graph","filters","dashboardId","gridColumn","gridRow","colSpan","rowSpan","createdAt","updatedAt"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Graph not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]},"patch":{"operationId":"patchApiGraphsById","description":"Update a custom graph's name, definition, or filters","responses":{"200":{"description":"Graph updated","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"graph":{"type":"object","additionalProperties":{}},"filters":{"type":["object","null"],"additionalProperties":{}},"dashboardId":{"type":["string","null"]},"gridColumn":{"type":"number"},"gridRow":{"type":"number"},"colSpan":{"type":"number"},"rowSpan":{"type":"number"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","name","graph","filters","dashboardId","gridColumn","gridRow","colSpan","rowSpan","createdAt","updatedAt"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Graph not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1},"graph":{"type":"object","additionalProperties":{}},"filters":{"type":"object","additionalProperties":{}}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]},"delete":{"operationId":"deleteApiGraphsById","description":"Delete a custom graph","responses":{"200":{"description":"Graph deleted","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"deleted":{"type":"boolean"}},"required":["id","deleted"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Graph not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]}},"/api/v1/langy/control/connect/register":{"post":{"operationId":"registerLangyControlSession","responses":{"200":{"description":"The folder is shared","content":{"application/json":{"schema":{"type":"object","properties":{"frame":{"anyOf":[{"type":"object","properties":{"protocol":{"type":"number","const":1},"type":{"type":"string","const":"registered"},"instanceId":{"type":"string"},"heartbeatIntervalMs":{"type":"integer","exclusiveMinimum":0},"conversation":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"url":{"type":"string"}},"required":["id","title","url"]},"policy":{"type":"object","properties":{"skipPermissions":{"type":"boolean"}},"required":["skipPermissions"]}},"required":["protocol","type","instanceId","heartbeatIntervalMs","conversation","policy"]},{"type":"object","properties":{"protocol":{"type":"number","const":1},"type":{"type":"string","const":"refused"},"code":{"type":"string","enum":["api_key_invalid","key_type_not_allowed","conversation_mismatch","workspace_already_connected","replica_count_unsupported","protocol_invalid"]},"message":{"type":"string"}},"required":["protocol","type","code","message"]}],"description":"The registered frame, or the refused frame with its reason."},"instanceToken":{"type":"string","description":"The token the poll and frames endpoints are addressed with, in the X-Agent-Instance-Token header. Present when the register was accepted."}},"required":["frame"]}}}},"401":{"description":"The session key is not valid: a refused frame"},"403":{"description":"The key is not a Langy session key, or it controls no conversation: a refused frame"},"422":{"description":"The body is not a register frame"}},"description":"Share a folder over HTTP, for a network that blocks WebSockets. The body is the register frame of the control protocol. Answers with the registered frame and the instance token the poll and frames endpoints are addressed with, or with a refused frame.","tags":["Langy"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"protocol":{"type":"number","enum":[1]},"type":{"type":"string","enum":["register"]},"cli":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":64},"version":{"type":"string","minLength":1,"maxLength":64}},"required":["name","version"],"additionalProperties":false},"instance":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128},"hostname":{"type":"string","maxLength":255},"username":{"type":"string","maxLength":255},"pid":{"type":"integer","minimum":0},"startedAt":{"type":"string","maxLength":64},"inFlightCallIds":{"type":"array","items":{"type":"string","maxLength":128},"maxItems":1000,"default":[]}},"required":["id","hostname","username","pid","startedAt"],"additionalProperties":false},"workspace":{"type":"object","properties":{"root":{"type":"string","minLength":1,"maxLength":4096},"name":{"type":"string","minLength":1,"maxLength":255},"gitRepository":{"type":"boolean"},"gitBranch":{"type":"string","maxLength":255},"gitRemote":{"type":"string","maxLength":2048},"gitDirty":{"type":"boolean"},"os":{"type":"string","maxLength":64},"nodeVersion":{"type":"string","maxLength":64},"pythonVersion":{"type":"string","maxLength":64},"ghAuthenticated":{"type":"boolean"},"packageManager":{"type":"string","maxLength":32}},"required":["root","name","os"],"additionalProperties":false}},"required":["protocol","type","cli","instance","workspace"],"additionalProperties":false}}}},"security":[{"project_api_key":[]}]}},"/api/v1/langy/control/connect/poll":{"get":{"operationId":"pollLangyControlSession","responses":{"200":{"description":"The frames waiting for the folder, possibly none","content":{"application/json":{"schema":{"type":"object","properties":{"frames":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"protocol":{"type":"number","const":1},"type":{"type":"string","const":"registered"},"instanceId":{"type":"string"},"heartbeatIntervalMs":{"type":"integer","exclusiveMinimum":0},"conversation":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"url":{"type":"string"}},"required":["id","title","url"]},"policy":{"type":"object","properties":{"skipPermissions":{"type":"boolean"}},"required":["skipPermissions"]}},"required":["protocol","type","instanceId","heartbeatIntervalMs","conversation","policy"]},{"type":"object","properties":{"protocol":{"type":"number","const":1},"type":{"type":"string","const":"refused"},"code":{"type":"string","enum":["api_key_invalid","key_type_not_allowed","conversation_mismatch","workspace_already_connected","replica_count_unsupported","protocol_invalid"]},"message":{"type":"string"}},"required":["protocol","type","code","message"]},{"type":"object","properties":{"protocol":{"type":"number","const":1},"type":{"type":"string","const":"call"},"call":{"allOf":[{"type":"object","properties":{"callId":{"type":"string"},"conversationId":{"type":"string"},"turnId":{"type":"string"},"deadlineAt":{"type":"integer"}},"required":["callId","conversationId","turnId","deadlineAt"]},{"oneOf":[{"type":"object","properties":{"tool":{"type":"string","const":"local_read"},"params":{"type":"object","properties":{"path":{"type":"string","minLength":1,"maxLength":4096},"offset":{"type":"integer","exclusiveMinimum":0},"limit":{"type":"integer","exclusiveMinimum":0}},"required":["path"]}},"required":["tool","params"]},{"type":"object","properties":{"tool":{"type":"string","const":"local_write"},"params":{"type":"object","properties":{"path":{"type":"string","minLength":1,"maxLength":4096},"content":{"type":"string"}},"required":["path","content"]}},"required":["tool","params"]},{"type":"object","properties":{"tool":{"type":"string","const":"local_edit"},"params":{"type":"object","properties":{"path":{"type":"string","minLength":1,"maxLength":4096},"edits":{"type":"array","items":{"anyOf":[{"type":"object","properties":{"oldText":{"type":"string","minLength":1},"newText":{"type":"string"}},"required":["oldText","newText"]},{"type":"object","properties":{"append":{"type":"string","minLength":1}},"required":["append"]}]},"minItems":1,"maxItems":200}},"required":["path","edits"]}},"required":["tool","params"]},{"type":"object","properties":{"tool":{"type":"string","const":"local_bash"},"params":{"type":"object","properties":{"command":{"type":"string","minLength":1,"maxLength":20000},"timeout":{"type":"integer","exclusiveMinimum":0},"background":{"type":"boolean"}},"required":["command"]}},"required":["tool","params"]},{"type":"object","properties":{"tool":{"type":"string","const":"local_grep"},"params":{"type":"object","properties":{"pattern":{"type":"string","minLength":1,"maxLength":2000},"path":{"type":"string","maxLength":4096},"glob":{"type":"string","maxLength":500},"ignoreCase":{"type":"boolean"},"literal":{"type":"boolean"},"context":{"type":"integer","minimum":0,"maximum":50},"limit":{"type":"integer","exclusiveMinimum":0,"maximum":5000}},"required":["pattern"]}},"required":["tool","params"]},{"type":"object","properties":{"tool":{"type":"string","const":"local_find"},"params":{"type":"object","properties":{"pattern":{"type":"string","minLength":1,"maxLength":500},"path":{"type":"string","maxLength":4096},"limit":{"type":"integer","exclusiveMinimum":0,"maximum":20000}},"required":["pattern"]}},"required":["tool","params"]},{"type":"object","properties":{"tool":{"type":"string","const":"local_ls"},"params":{"type":"object","properties":{"path":{"type":"string","maxLength":4096},"limit":{"type":"integer","exclusiveMinimum":0,"maximum":20000}}}},"required":["tool","params"]},{"type":"object","properties":{"tool":{"type":"string","const":"local_langwatch_env"},"params":{"type":"object","properties":{"path":{"type":"string","minLength":1,"maxLength":4096}}}},"required":["tool","params"]}]}]}},"required":["protocol","type","call"]},{"type":"object","properties":{"protocol":{"type":"number","const":1},"type":{"type":"string","const":"cancel"},"callId":{"type":"string"}},"required":["protocol","type","callId"]},{"type":"object","properties":{"protocol":{"type":"number","const":1},"type":{"type":"string","const":"permission"},"callId":{"type":"string"},"decision":{"type":"string","enum":["allow_once","allow_pattern","deny","expired"]}},"required":["protocol","type","callId","decision"]},{"type":"object","properties":{"protocol":{"type":"number","const":1},"type":{"type":"string","const":"policy"},"skipPermissions":{"type":"boolean"}},"required":["protocol","type","skipPermissions"]},{"type":"object","properties":{"protocol":{"type":"number","const":1},"type":{"type":"string","const":"disconnect"},"reason":{"type":"string","maxLength":500}},"required":["protocol","type","reason"]}]},"description":"The frames waiting for the folder; empty once the poll wait passes with none."}},"required":["frames"]}}}},"410":{"description":"The instance token is not known; share the folder again"}},"description":"Wait for the next frames of a shared folder, then answer with what is waiting or with an empty list. Each poll is also the folder's heartbeat, so a command line that polls reads connected. Addressed with the instance token in the X-Agent-Instance-Token header.","tags":["Langy"],"security":[{"project_api_key":[]}]}},"/api/v1/langy/control/connect/frames":{"post":{"operationId":"postLangyControlFrames","responses":{"200":{"description":"The frames were taken","content":{"application/json":{"schema":{"type":"object","properties":{"accepted":{"type":"integer","description":"How many frames were taken."}},"required":["accepted"]}}}},"410":{"description":"The instance token is not known; share the folder again"},"422":{"description":"The body is not a list of frames"}},"description":"Post the frames the command line has for the platform: the acknowledgement of a call, its result, a permission the developer has to answer first, and the deregister that ends the share.","tags":["Langy"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"frames":{"type":"array","items":{"anyOf":[{"type":"object","properties":{"protocol":{"type":"number","enum":[1]},"type":{"type":"string","enum":["register"]},"cli":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":64},"version":{"type":"string","minLength":1,"maxLength":64}},"required":["name","version"],"additionalProperties":false},"instance":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128},"hostname":{"type":"string","maxLength":255},"username":{"type":"string","maxLength":255},"pid":{"type":"integer","minimum":0},"startedAt":{"type":"string","maxLength":64},"inFlightCallIds":{"type":"array","items":{"type":"string","maxLength":128},"maxItems":1000,"default":[]}},"required":["id","hostname","username","pid","startedAt"],"additionalProperties":false},"workspace":{"type":"object","properties":{"root":{"type":"string","minLength":1,"maxLength":4096},"name":{"type":"string","minLength":1,"maxLength":255},"gitRepository":{"type":"boolean"},"gitBranch":{"type":"string","maxLength":255},"gitRemote":{"type":"string","maxLength":2048},"gitDirty":{"type":"boolean"},"os":{"type":"string","maxLength":64},"nodeVersion":{"type":"string","maxLength":64},"pythonVersion":{"type":"string","maxLength":64},"ghAuthenticated":{"type":"boolean"},"packageManager":{"type":"string","maxLength":32}},"required":["root","name","os"],"additionalProperties":false}},"required":["protocol","type","cli","instance","workspace"],"additionalProperties":false},{"type":"object","properties":{"protocol":{"type":"number","enum":[1]},"type":{"type":"string","enum":["ack"]},"callId":{"type":"string"}},"required":["protocol","type","callId"],"additionalProperties":false},{"type":"object","properties":{"protocol":{"type":"number","enum":[1]},"type":{"type":"string","enum":["result"]},"callId":{"type":"string"},"ok":{"type":"boolean"},"text":{"type":"string"},"output":{"type":"object","properties":{"exitCode":{"type":"integer","nullable":true},"stdout":{"type":"string"},"stderr":{"type":"string"},"truncated":{"type":"boolean"},"logPath":{"type":"string"},"pid":{"type":"integer","exclusiveMinimum":0},"durationMs":{"type":"integer","minimum":0}},"required":["exitCode","stdout","stderr","truncated","durationMs"],"additionalProperties":false},"error":{"type":"object","properties":{"code":{"type":"string","enum":["path_refused","command_refused","permission_denied","permission_expired","cancelled","timeout","exec_failed","not_found","key_refused"]},"message":{"type":"string","maxLength":4000}},"required":["code","message"],"additionalProperties":false}},"required":["protocol","type","callId","ok"],"additionalProperties":false},{"type":"object","properties":{"protocol":{"type":"number","enum":[1]},"type":{"type":"string","enum":["permission_required"]},"callId":{"type":"string"},"summary":{"type":"string","maxLength":4000},"pattern":{"type":"string","maxLength":500},"reason":{"type":"string","maxLength":500},"skipOffered":{"type":"boolean"},"segments":{"type":"array","items":{"type":"object","properties":{"command":{"type":"string","maxLength":4000},"pattern":{"type":"string","maxLength":500},"readOnly":{"type":"boolean"}},"required":["command","pattern","readOnly"],"additionalProperties":false},"maxItems":50},"timeoutSeconds":{"type":"integer","exclusiveMinimum":0,"maximum":3600}},"required":["protocol","type","callId","summary","pattern","reason","skipOffered"],"additionalProperties":false},{"type":"object","properties":{"protocol":{"type":"number","enum":[1]},"type":{"type":"string","enum":["permission_answered"]},"callId":{"type":"string"},"decision":{"type":"string","enum":["allow_once","allow_pattern","deny"]},"patterns":{"type":"array","items":{"type":"string","maxLength":500},"maxItems":50}},"required":["protocol","type","callId","decision"],"additionalProperties":false},{"type":"object","properties":{"protocol":{"type":"number","enum":[1]},"type":{"type":"string","enum":["deregister"]}},"required":["protocol","type"],"additionalProperties":false}]},"minItems":1,"maxItems":100,"description":"Ack, result, permission_required and deregister frames, in order."}},"required":["frames"],"additionalProperties":false}}}},"security":[{"project_api_key":[]}]}},"/api/v1/langy/control/requests":{"get":{"operationId":"listLangyControlRequests","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"requests":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"conversationId":{"type":"string"},"conversationTitle":{"type":"string"},"conversationUrl":{"type":"string"},"projectId":{"type":"string"},"projectName":{"type":"string"},"createdAt":{"type":"string"},"expiresAt":{"type":"string"}},"required":["id","conversationId","conversationTitle","conversationUrl","projectId","projectName","createdAt","expiresAt"]}}},"required":["requests"]}}}}},"description":"List the open requests Langy made for a folder of mine, on every project I can read. Only the person Langy asked ever sees a request, and each one expires fifteen minutes after it was made.","tags":["Langy"],"security":[{"project_api_key":[]}]}},"/api/v1/langy/control/requests/{id}/approve":{"post":{"operationId":"approveLangyControlRequest","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"sessionKey":{"type":"string"},"endpoint":{"type":"string"},"conversation":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"url":{"type":"string"}},"required":["id","title","url"]}},"required":["sessionKey","endpoint","conversation"]}}}}},"description":"Approve one request and share the current folder with the conversation that asked. Answers with a Langy session key scoped to that conversation, which is never shown again. A request is single use: a second approval is refused.","tags":["Langy"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1},"required":true,"description":"The control request id."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"workspace":{"type":"object","properties":{"root":{"type":"string","minLength":1,"maxLength":4096},"name":{"type":"string","minLength":1,"maxLength":255},"gitRepository":{"type":"boolean"},"gitBranch":{"type":"string","maxLength":255},"gitRemote":{"type":"string","maxLength":2048},"gitDirty":{"type":"boolean"},"os":{"type":"string","maxLength":64},"nodeVersion":{"type":"string","maxLength":64},"pythonVersion":{"type":"string","maxLength":64},"ghAuthenticated":{"type":"boolean"},"packageManager":{"type":"string","maxLength":32}},"required":["root","name","os"]}},"required":["workspace"]}}}},"security":[{"project_api_key":[]}]}},"/api/v1/langy/control/requests/{id}/cancel":{"post":{"operationId":"cancelLangyControlRequest","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"The request that was cancelled."},"cancelled":{"type":"boolean","const":true,"description":"Always true once the request is gone."}},"required":["id","cancelled"]}}}}},"description":"Refuse one request from the terminal. The card in the chat reads that sharing was cancelled, and Langy's next turn offers the choice again.","tags":["Langy"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1},"required":true,"description":"The control request id."}],"security":[{"project_api_key":[]}]}},"/api/me/usage":{"get":{"operationId":"getApiMeUsage","description":"Personal AI usage for the current month (or an explicit window): spend, billed spend, request + token counts, per-day buckets, and per-model breakdown. Requires a personal-project API key.","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"summary":{"type":"object","properties":{"spentUsd":{"type":"number"},"billedUsd":{"type":"number"},"requests":{"type":"number"},"promptTokens":{"type":"number"},"completionTokens":{"type":"number"},"mostUsedModel":{"type":["object","null"],"properties":{"name":{"type":"string"},"usagePct":{"type":"number"}},"required":["name","usagePct"]}},"required":["spentUsd","billedUsd","requests","promptTokens","completionTokens","mostUsedModel"]},"dailyBuckets":{"type":"array","items":{"type":"object","properties":{"day":{"type":"string"},"spentUsd":{"type":"number"},"billedUsd":{"type":"number"},"requests":{"type":"number"}},"required":["day","spentUsd","billedUsd","requests"]}},"breakdownByModel":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"spentUsd":{"type":"number"},"billedUsd":{"type":"number"},"requests":{"type":"number"}},"required":["label","spentUsd","billedUsd","requests"]}}},"required":["summary","dailyBuckets","breakdownByModel"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"parameters":[{"in":"query","name":"windowStartMs","schema":{"type":"integer","minimum":-8640000000000000,"maximum":8640000000000000}},{"in":"query","name":"windowEndMs","schema":{"type":"integer","minimum":-8640000000000000,"maximum":8640000000000000}}],"security":[{"project_api_key":[]}]}},"/api/me/project":{"get":{"operationId":"getApiMeProject","description":"Identity of the project the calling API key belongs to: id, name, slug and whether it is a personal workspace project. Lets a client (the CLI's identity notice, a widget) say which project a key targets without any further access.","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"isPersonal":{"type":"boolean"}},"required":["id","name","slug","isPersonal"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"security":[{"project_api_key":[]}]}},"/api/prompts":{"get":{"operationId":"getApiPrompts","description":"Get all prompts for a project","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"handle":{"type":["string","null"]},"scope":{"type":"string","enum":["ORGANIZATION","PROJECT"]},"name":{"type":"string"},"updatedAt":{"type":"string"},"projectId":{"type":"string"},"organizationId":{"type":"string"},"versionId":{"type":"string"},"authorId":{"type":["string","null"]},"version":{"type":"number"},"createdAt":{"type":"string"},"commitMessage":{"type":["string","null"]},"prompt":{"type":"string"},"messages":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string","enum":["user","assistant","system"]},"content":{"type":"string"}},"required":["role","content"]},"default":[]},"inputs":{"type":"array","items":{"type":"object","properties":{"identifier":{"type":"string","minLength":1},"type":{"type":"string","enum":["str","float","bool","image","file","list","list[str]","list[float]","list[int]","list[bool]","dict","chat_messages"]}},"required":["identifier","type"]},"default":[]},"outputs":{"type":"array","items":{"type":"object","properties":{"identifier":{"type":"string","minLength":1},"type":{"type":"string","enum":["str","float","bool","json_schema"]},"json_schema":{"type":"object","properties":{"type":{"type":"string","minLength":1}},"required":["type"],"additionalProperties":true}},"required":["identifier","type"]},"minItems":1},"model":{"type":"string","minLength":1},"temperature":{"type":"number"},"maxTokens":{"type":"number"},"demonstrations":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"inline":{"type":"object","properties":{"records":{"type":"object","additionalProperties":{"type":"array","items":{}}},"columnTypes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"anyOf":[{"type":"string","const":"string"},{"type":"string","const":"boolean"},{"type":"string","const":"number"},{"type":"string","const":"date"},{"type":"string","const":"list"},{"type":"string","const":"json"},{"type":"string","const":"spans"},{"type":"string","const":"rag_contexts"},{"type":"string","const":"chat_messages"},{"type":"string","const":"annotations"},{"type":"string","const":"evaluations"},{"type":"string","const":"image"},{"type":"string","const":"file"}]}},"required":["name","type"]}}},"required":["records","columnTypes"]}}},"promptingTechnique":{"type":"object","properties":{"type":{"type":"string","enum":["few_shot","in_context","chain_of_thought"]},"demonstrations":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"inline":{"type":"object","properties":{"records":{"type":"object","additionalProperties":{"type":"array","items":{}}},"columnTypes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"anyOf":[{"type":"string","const":"string"},{"type":"string","const":"boolean"},{"type":"string","const":"number"},{"type":"string","const":"date"},{"type":"string","const":"list"},{"type":"string","const":"json"},{"type":"string","const":"spans"},{"type":"string","const":"rag_contexts"},{"type":"string","const":"chat_messages"},{"type":"string","const":"annotations"},{"type":"string","const":"evaluations"},{"type":"string","const":"image"},{"type":"string","const":"file"}]}},"required":["name","type"]}}},"required":["records","columnTypes"]}}}},"required":["type"]},"responseFormat":{"type":"object","properties":{"type":{"type":"string","enum":["json_schema"]},"json_schema":{"type":["object","null"],"properties":{"name":{"type":"string"},"schema":{"type":"object","additionalProperties":true}},"required":["name","schema"]}},"required":["type","json_schema"]},"tags":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"versionId":{"type":"string"}},"required":["name","versionId"]},"default":[]},"parameters":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/JsonValue"},"default":{}}},"required":["id","handle","scope","name","updatedAt","projectId","organizationId","versionId","version","createdAt","prompt","outputs","model","messages","inputs","tags","parameters"]}}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"security":[{"project_api_key":[]}]},"post":{"operationId":"postApiPrompts","description":"Create a new prompt with default initial version","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"handle":{"type":["string","null"]},"scope":{"type":"string","enum":["ORGANIZATION","PROJECT"]},"name":{"type":"string"},"updatedAt":{"type":"string"},"projectId":{"type":"string"},"organizationId":{"type":"string"},"versionId":{"type":"string"},"authorId":{"type":["string","null"]},"version":{"type":"number"},"createdAt":{"type":"string"},"commitMessage":{"type":["string","null"]},"prompt":{"type":"string"},"messages":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string","enum":["user","assistant","system"]},"content":{"type":"string"}},"required":["role","content"]},"default":[]},"inputs":{"type":"array","items":{"type":"object","properties":{"identifier":{"type":"string","minLength":1},"type":{"type":"string","enum":["str","float","bool","image","file","list","list[str]","list[float]","list[int]","list[bool]","dict","chat_messages"]}},"required":["identifier","type"]},"default":[]},"outputs":{"type":"array","items":{"type":"object","properties":{"identifier":{"type":"string","minLength":1},"type":{"type":"string","enum":["str","float","bool","json_schema"]},"json_schema":{"type":"object","properties":{"type":{"type":"string","minLength":1}},"required":["type"],"additionalProperties":true}},"required":["identifier","type"]},"minItems":1},"model":{"type":"string","minLength":1},"temperature":{"type":"number"},"maxTokens":{"type":"number"},"demonstrations":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"inline":{"type":"object","properties":{"records":{"type":"object","additionalProperties":{"type":"array","items":{}}},"columnTypes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"anyOf":[{"type":"string","const":"string"},{"type":"string","const":"boolean"},{"type":"string","const":"number"},{"type":"string","const":"date"},{"type":"string","const":"list"},{"type":"string","const":"json"},{"type":"string","const":"spans"},{"type":"string","const":"rag_contexts"},{"type":"string","const":"chat_messages"},{"type":"string","const":"annotations"},{"type":"string","const":"evaluations"},{"type":"string","const":"image"},{"type":"string","const":"file"}]}},"required":["name","type"]}}},"required":["records","columnTypes"]}}},"promptingTechnique":{"type":"object","properties":{"type":{"type":"string","enum":["few_shot","in_context","chain_of_thought"]},"demonstrations":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"inline":{"type":"object","properties":{"records":{"type":"object","additionalProperties":{"type":"array","items":{}}},"columnTypes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"anyOf":[{"type":"string","const":"string"},{"type":"string","const":"boolean"},{"type":"string","const":"number"},{"type":"string","const":"date"},{"type":"string","const":"list"},{"type":"string","const":"json"},{"type":"string","const":"spans"},{"type":"string","const":"rag_contexts"},{"type":"string","const":"chat_messages"},{"type":"string","const":"annotations"},{"type":"string","const":"evaluations"},{"type":"string","const":"image"},{"type":"string","const":"file"}]}},"required":["name","type"]}}},"required":["records","columnTypes"]}}}},"required":["type"]},"responseFormat":{"type":"object","properties":{"type":{"type":"string","enum":["json_schema"]},"json_schema":{"type":["object","null"],"properties":{"name":{"type":"string"},"schema":{"type":"object","additionalProperties":true}},"required":["name","schema"]}},"required":["type","json_schema"]},"tags":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"versionId":{"type":"string"}},"required":["name","versionId"]},"default":[]},"parameters":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/JsonValue"},"default":{}}},"required":["id","handle","scope","name","updatedAt","projectId","organizationId","versionId","version","createdAt","prompt","outputs","model","messages","inputs","tags","parameters"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error","message"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"handle":{"type":"string","pattern":"^[a-z0-9_-]+(?:\\/[a-z0-9_-]+)?$"},"scope":{"type":"string","enum":["ORGANIZATION","PROJECT"],"default":"PROJECT"},"model":{"type":"string"},"temperature":{"type":"number"},"maxTokens":{"type":"number"},"commitMessage":{"type":"string"},"authorId":{"type":"string"},"prompt":{"type":"string"},"messages":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string","enum":["user","assistant","system"]},"content":{"type":"string"}},"required":["role","content"]}},"inputs":{"type":"array","items":{"type":"object","properties":{"identifier":{"type":"string","minLength":1},"type":{"type":"string","enum":["str","float","bool","image","file","list","list[str]","list[float]","list[int]","list[bool]","dict","chat_messages"]}},"required":["identifier","type"]}},"outputs":{"type":"array","items":{"type":"object","properties":{"identifier":{"type":"string","minLength":1},"type":{"type":"string","enum":["str","float","bool","json_schema"]},"json_schema":{"type":"object","properties":{"type":{"type":"string","minLength":1}},"required":["type"],"additionalProperties":true}},"required":["identifier","type"]}},"schemaVersion":{"type":"string","enum":["1.0"]},"tags":{"type":"array","items":{"type":"string","minLength":1}},"parameters":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/JsonValue"},"default":{}}},"required":["handle"],"additionalProperties":false}}}},"security":[{"project_api_key":[]}]}},"/api/prompts/{id}/tags/{tag}":{"put":{"operationId":"putApiPromptsByIdTagsByTag","description":"Assign a tag (e.g. \"production\", \"staging\") to a specific prompt version","parameters":[{"name":"tag","in":"path","description":"The tag to assign (e.g., \"production\", \"staging\", or a custom tag)","required":true,"schema":{"type":"string"}},{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"configId":{"type":"string"},"versionId":{"type":"string"},"tag":{"type":"string"},"updatedAt":{"type":"string"}},"required":["configId","versionId","tag","updatedAt"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Prompt not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Invalid tag or version","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"versionId":{"type":"string"}},"required":["versionId"]}}}},"security":[{"project_api_key":[]}]}},"/api/prompts/tags":{"get":{"operationId":"getApiPromptsTags","description":"List all prompt tag definitions for the organization","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"createdAt":{"type":"string"}},"required":["id","name","createdAt"]}}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"security":[{"project_api_key":[]}]},"post":{"operationId":"postApiPromptsTags","description":"Create a custom prompt tag definition for the organization","responses":{"201":{"description":"Tag created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"createdAt":{"type":"string"}},"required":["id","name","createdAt"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"}},"required":["name"]}}}},"security":[{"project_api_key":[]}]}},"/api/prompts/tags/{tag}":{"put":{"operationId":"putApiPromptsTagsByTag","description":"Rename a prompt tag definition","responses":{"200":{"description":"Tag renamed","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"createdAt":{"type":"string"}},"required":["id","name","createdAt"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"}},"required":["name"]}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"tag","required":true}],"security":[{"project_api_key":[]}]},"delete":{"operationId":"deleteApiPromptsTagsByTag","description":"Delete a prompt tag definition and cascade to assignments","responses":{"204":{"description":"Tag deleted"},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"tag","required":true}],"security":[{"project_api_key":[]}]}},"/api/prompts/{id}/versions":{"get":{"operationId":"getApiPromptsByIdVersions","description":"Get all versions for a prompt. Does not include base prompt data, only versioned data.","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"handle":{"type":["string","null"]},"scope":{"type":"string","enum":["ORGANIZATION","PROJECT"]},"name":{"type":"string"},"updatedAt":{"type":"string"},"projectId":{"type":"string"},"organizationId":{"type":"string"},"versionId":{"type":"string"},"authorId":{"type":["string","null"]},"version":{"type":"number"},"createdAt":{"type":"string"},"commitMessage":{"type":["string","null"]},"prompt":{"type":"string"},"messages":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string","enum":["user","assistant","system"]},"content":{"type":"string"}},"required":["role","content"]},"default":[]},"inputs":{"type":"array","items":{"type":"object","properties":{"identifier":{"type":"string","minLength":1},"type":{"type":"string","enum":["str","float","bool","image","file","list","list[str]","list[float]","list[int]","list[bool]","dict","chat_messages"]}},"required":["identifier","type"]},"default":[]},"outputs":{"type":"array","items":{"type":"object","properties":{"identifier":{"type":"string","minLength":1},"type":{"type":"string","enum":["str","float","bool","json_schema"]},"json_schema":{"type":"object","properties":{"type":{"type":"string","minLength":1}},"required":["type"],"additionalProperties":true}},"required":["identifier","type"]},"minItems":1},"model":{"type":"string","minLength":1},"temperature":{"type":"number"},"maxTokens":{"type":"number"},"demonstrations":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"inline":{"type":"object","properties":{"records":{"type":"object","additionalProperties":{"type":"array","items":{}}},"columnTypes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"anyOf":[{"type":"string","const":"string"},{"type":"string","const":"boolean"},{"type":"string","const":"number"},{"type":"string","const":"date"},{"type":"string","const":"list"},{"type":"string","const":"json"},{"type":"string","const":"spans"},{"type":"string","const":"rag_contexts"},{"type":"string","const":"chat_messages"},{"type":"string","const":"annotations"},{"type":"string","const":"evaluations"},{"type":"string","const":"image"},{"type":"string","const":"file"}]}},"required":["name","type"]}}},"required":["records","columnTypes"]}}},"promptingTechnique":{"type":"object","properties":{"type":{"type":"string","enum":["few_shot","in_context","chain_of_thought"]},"demonstrations":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"inline":{"type":"object","properties":{"records":{"type":"object","additionalProperties":{"type":"array","items":{}}},"columnTypes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"anyOf":[{"type":"string","const":"string"},{"type":"string","const":"boolean"},{"type":"string","const":"number"},{"type":"string","const":"date"},{"type":"string","const":"list"},{"type":"string","const":"json"},{"type":"string","const":"spans"},{"type":"string","const":"rag_contexts"},{"type":"string","const":"chat_messages"},{"type":"string","const":"annotations"},{"type":"string","const":"evaluations"},{"type":"string","const":"image"},{"type":"string","const":"file"}]}},"required":["name","type"]}}},"required":["records","columnTypes"]}}}},"required":["type"]},"responseFormat":{"type":"object","properties":{"type":{"type":"string","enum":["json_schema"]},"json_schema":{"type":["object","null"],"properties":{"name":{"type":"string"},"schema":{"type":"object","additionalProperties":true}},"required":["name","schema"]}},"required":["type","json_schema"]},"tags":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"versionId":{"type":"string"}},"required":["name","versionId"]},"default":[]},"parameters":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/JsonValue"},"default":{}}},"required":["id","handle","scope","name","updatedAt","projectId","organizationId","versionId","version","createdAt","prompt","outputs","model","messages","inputs","tags","parameters"]}}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Prompt not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]}},"/api/prompts/{id}/versions/{versionId}/restore":{"post":{"operationId":"postApiPromptsByIdVersionsByVersionIdRestore","description":"Restore a prompt to a previous version. Creates a new version with the same config data as the specified version.","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"handle":{"type":["string","null"]},"scope":{"type":"string","enum":["ORGANIZATION","PROJECT"]},"name":{"type":"string"},"updatedAt":{"type":"string"},"projectId":{"type":"string"},"organizationId":{"type":"string"},"versionId":{"type":"string"},"authorId":{"type":["string","null"]},"version":{"type":"number"},"createdAt":{"type":"string"},"commitMessage":{"type":["string","null"]},"prompt":{"type":"string"},"messages":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string","enum":["user","assistant","system"]},"content":{"type":"string"}},"required":["role","content"]},"default":[]},"inputs":{"type":"array","items":{"type":"object","properties":{"identifier":{"type":"string","minLength":1},"type":{"type":"string","enum":["str","float","bool","image","file","list","list[str]","list[float]","list[int]","list[bool]","dict","chat_messages"]}},"required":["identifier","type"]},"default":[]},"outputs":{"type":"array","items":{"type":"object","properties":{"identifier":{"type":"string","minLength":1},"type":{"type":"string","enum":["str","float","bool","json_schema"]},"json_schema":{"type":"object","properties":{"type":{"type":"string","minLength":1}},"required":["type"],"additionalProperties":true}},"required":["identifier","type"]},"minItems":1},"model":{"type":"string","minLength":1},"temperature":{"type":"number"},"maxTokens":{"type":"number"},"demonstrations":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"inline":{"type":"object","properties":{"records":{"type":"object","additionalProperties":{"type":"array","items":{}}},"columnTypes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"anyOf":[{"type":"string","const":"string"},{"type":"string","const":"boolean"},{"type":"string","const":"number"},{"type":"string","const":"date"},{"type":"string","const":"list"},{"type":"string","const":"json"},{"type":"string","const":"spans"},{"type":"string","const":"rag_contexts"},{"type":"string","const":"chat_messages"},{"type":"string","const":"annotations"},{"type":"string","const":"evaluations"},{"type":"string","const":"image"},{"type":"string","const":"file"}]}},"required":["name","type"]}}},"required":["records","columnTypes"]}}},"promptingTechnique":{"type":"object","properties":{"type":{"type":"string","enum":["few_shot","in_context","chain_of_thought"]},"demonstrations":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"inline":{"type":"object","properties":{"records":{"type":"object","additionalProperties":{"type":"array","items":{}}},"columnTypes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"anyOf":[{"type":"string","const":"string"},{"type":"string","const":"boolean"},{"type":"string","const":"number"},{"type":"string","const":"date"},{"type":"string","const":"list"},{"type":"string","const":"json"},{"type":"string","const":"spans"},{"type":"string","const":"rag_contexts"},{"type":"string","const":"chat_messages"},{"type":"string","const":"annotations"},{"type":"string","const":"evaluations"},{"type":"string","const":"image"},{"type":"string","const":"file"}]}},"required":["name","type"]}}},"required":["records","columnTypes"]}}}},"required":["type"]},"responseFormat":{"type":"object","properties":{"type":{"type":"string","enum":["json_schema"]},"json_schema":{"type":["object","null"],"properties":{"name":{"type":"string"},"schema":{"type":"object","additionalProperties":true}},"required":["name","schema"]}},"required":["type","json_schema"]},"tags":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"versionId":{"type":"string"}},"required":["name","versionId"]},"default":[]},"parameters":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/JsonValue"},"default":{}}},"required":["id","handle","scope","name","updatedAt","projectId","organizationId","versionId","version","createdAt","prompt","outputs","model","messages","inputs","tags","parameters"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Prompt or version not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true},{"schema":{"type":"string"},"in":"path","name":"versionId","required":true}],"security":[{"project_api_key":[]}]}},"/api/prompts/{id}":{"get":{"operationId":"getApiPromptsById","description":"Get a specific prompt by slug, with optional shorthand syntax for tags and versions. Pass a bare slug like \"pizza-prompt\" to get the latest version, \"pizza-prompt:production\" to resolve a tagged version, or \"pizza-prompt:2\" to fetch version 2. Alternatively, use the tag or version query parameters with a bare slug.","parameters":[{"name":"id","in":"path","description":"Prompt slug or shorthand. Supports three formats: (1) bare slug — \"pizza-prompt\" returns the latest version; (2) slug:tag — \"pizza-prompt:production\" returns the version pointed to by that tag; (3) slug:version — \"pizza-prompt:2\" returns that specific version number. \"slug:latest\" is equivalent to the bare slug. Cannot be combined with the tag or version query parameters.","required":true,"schema":{"type":"string"}},{"name":"version","in":"query","description":"Specific version number to retrieve. Cannot be used when the id path already contains a shorthand suffix.","required":false,"schema":{"type":"integer","minimum":0}},{"name":"tag","in":"query","description":"Fetch the version pointed to by this tag (e.g., \"production\", \"staging\"). Cannot be used when the id path already contains a shorthand suffix.","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"handle":{"type":["string","null"]},"scope":{"type":"string","enum":["ORGANIZATION","PROJECT"]},"name":{"type":"string"},"updatedAt":{"type":"string"},"projectId":{"type":"string"},"organizationId":{"type":"string"},"versionId":{"type":"string"},"authorId":{"type":["string","null"]},"version":{"type":"number"},"createdAt":{"type":"string"},"commitMessage":{"type":["string","null"]},"prompt":{"type":"string"},"messages":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string","enum":["user","assistant","system"]},"content":{"type":"string"}},"required":["role","content"]},"default":[]},"inputs":{"type":"array","items":{"type":"object","properties":{"identifier":{"type":"string","minLength":1},"type":{"type":"string","enum":["str","float","bool","image","file","list","list[str]","list[float]","list[int]","list[bool]","dict","chat_messages"]}},"required":["identifier","type"]},"default":[]},"outputs":{"type":"array","items":{"type":"object","properties":{"identifier":{"type":"string","minLength":1},"type":{"type":"string","enum":["str","float","bool","json_schema"]},"json_schema":{"type":"object","properties":{"type":{"type":"string","minLength":1}},"required":["type"],"additionalProperties":true}},"required":["identifier","type"]},"minItems":1},"model":{"type":"string","minLength":1},"temperature":{"type":"number"},"maxTokens":{"type":"number"},"demonstrations":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"inline":{"type":"object","properties":{"records":{"type":"object","additionalProperties":{"type":"array","items":{}}},"columnTypes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"anyOf":[{"type":"string","const":"string"},{"type":"string","const":"boolean"},{"type":"string","const":"number"},{"type":"string","const":"date"},{"type":"string","const":"list"},{"type":"string","const":"json"},{"type":"string","const":"spans"},{"type":"string","const":"rag_contexts"},{"type":"string","const":"chat_messages"},{"type":"string","const":"annotations"},{"type":"string","const":"evaluations"},{"type":"string","const":"image"},{"type":"string","const":"file"}]}},"required":["name","type"]}}},"required":["records","columnTypes"]}}},"promptingTechnique":{"type":"object","properties":{"type":{"type":"string","enum":["few_shot","in_context","chain_of_thought"]},"demonstrations":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"inline":{"type":"object","properties":{"records":{"type":"object","additionalProperties":{"type":"array","items":{}}},"columnTypes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"anyOf":[{"type":"string","const":"string"},{"type":"string","const":"boolean"},{"type":"string","const":"number"},{"type":"string","const":"date"},{"type":"string","const":"list"},{"type":"string","const":"json"},{"type":"string","const":"spans"},{"type":"string","const":"rag_contexts"},{"type":"string","const":"chat_messages"},{"type":"string","const":"annotations"},{"type":"string","const":"evaluations"},{"type":"string","const":"image"},{"type":"string","const":"file"}]}},"required":["name","type"]}}},"required":["records","columnTypes"]}}}},"required":["type"]},"responseFormat":{"type":"object","properties":{"type":{"type":"string","enum":["json_schema"]},"json_schema":{"type":["object","null"],"properties":{"name":{"type":"string"},"schema":{"type":"object","additionalProperties":true}},"required":["name","schema"]}},"required":["type","json_schema"]},"tags":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"versionId":{"type":"string"}},"required":["name","versionId"]},"default":[]},"parameters":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/JsonValue"},"default":{}}},"required":["id","handle","scope","name","updatedAt","projectId","organizationId","versionId","version","createdAt","prompt","outputs","model","messages","inputs","tags","parameters"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Prompt not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"security":[{"project_api_key":[]}]},"put":{"operationId":"putApiPromptsById","description":"Update a prompt","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"handle":{"type":["string","null"]},"scope":{"type":"string","enum":["ORGANIZATION","PROJECT"]},"name":{"type":"string"},"updatedAt":{"type":"string"},"projectId":{"type":"string"},"organizationId":{"type":"string"},"versionId":{"type":"string"},"authorId":{"type":["string","null"]},"version":{"type":"number"},"createdAt":{"type":"string"},"commitMessage":{"type":["string","null"]},"prompt":{"type":"string"},"messages":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string","enum":["user","assistant","system"]},"content":{"type":"string"}},"required":["role","content"]},"default":[]},"inputs":{"type":"array","items":{"type":"object","properties":{"identifier":{"type":"string","minLength":1},"type":{"type":"string","enum":["str","float","bool","image","file","list","list[str]","list[float]","list[int]","list[bool]","dict","chat_messages"]}},"required":["identifier","type"]},"default":[]},"outputs":{"type":"array","items":{"type":"object","properties":{"identifier":{"type":"string","minLength":1},"type":{"type":"string","enum":["str","float","bool","json_schema"]},"json_schema":{"type":"object","properties":{"type":{"type":"string","minLength":1}},"required":["type"],"additionalProperties":true}},"required":["identifier","type"]},"minItems":1},"model":{"type":"string","minLength":1},"temperature":{"type":"number"},"maxTokens":{"type":"number"},"demonstrations":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"inline":{"type":"object","properties":{"records":{"type":"object","additionalProperties":{"type":"array","items":{}}},"columnTypes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"anyOf":[{"type":"string","const":"string"},{"type":"string","const":"boolean"},{"type":"string","const":"number"},{"type":"string","const":"date"},{"type":"string","const":"list"},{"type":"string","const":"json"},{"type":"string","const":"spans"},{"type":"string","const":"rag_contexts"},{"type":"string","const":"chat_messages"},{"type":"string","const":"annotations"},{"type":"string","const":"evaluations"},{"type":"string","const":"image"},{"type":"string","const":"file"}]}},"required":["name","type"]}}},"required":["records","columnTypes"]}}},"promptingTechnique":{"type":"object","properties":{"type":{"type":"string","enum":["few_shot","in_context","chain_of_thought"]},"demonstrations":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"inline":{"type":"object","properties":{"records":{"type":"object","additionalProperties":{"type":"array","items":{}}},"columnTypes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"anyOf":[{"type":"string","const":"string"},{"type":"string","const":"boolean"},{"type":"string","const":"number"},{"type":"string","const":"date"},{"type":"string","const":"list"},{"type":"string","const":"json"},{"type":"string","const":"spans"},{"type":"string","const":"rag_contexts"},{"type":"string","const":"chat_messages"},{"type":"string","const":"annotations"},{"type":"string","const":"evaluations"},{"type":"string","const":"image"},{"type":"string","const":"file"}]}},"required":["name","type"]}}},"required":["records","columnTypes"]}}}},"required":["type"]},"responseFormat":{"type":"object","properties":{"type":{"type":"string","enum":["json_schema"]},"json_schema":{"type":["object","null"],"properties":{"name":{"type":"string"},"schema":{"type":"object","additionalProperties":true}},"required":["name","schema"]}},"required":["type","json_schema"]},"tags":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"versionId":{"type":"string"}},"required":["name","versionId"]},"default":[]},"parameters":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/JsonValue"},"default":{}}},"required":["id","handle","scope","name","updatedAt","projectId","organizationId","versionId","version","createdAt","prompt","outputs","model","messages","inputs","tags","parameters"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Prompt not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error","message"]}}}},"422":{"description":"Invalid input","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"model":{"type":"string"},"temperature":{"type":"number"},"maxTokens":{"type":"number"},"commitMessage":{"type":"string"},"authorId":{"type":"string"},"prompt":{"type":"string"},"messages":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string","enum":["user","assistant","system"]},"content":{"type":"string"}},"required":["role","content"]}},"inputs":{"type":"array","items":{"type":"object","properties":{"identifier":{"type":"string","minLength":1},"type":{"type":"string","enum":["str","float","bool","image","file","list","list[str]","list[float]","list[int]","list[bool]","dict","chat_messages"]}},"required":["identifier","type"]}},"outputs":{"type":"array","items":{"type":"object","properties":{"identifier":{"type":"string","minLength":1},"type":{"type":"string","enum":["str","float","bool","json_schema"]},"json_schema":{"type":"object","properties":{"type":{"type":"string","minLength":1}},"required":["type"],"additionalProperties":true}},"required":["identifier","type"]}},"schemaVersion":{"type":"string","enum":["1.0"]},"tags":{"type":"array","items":{"type":"string","minLength":1}},"parameters":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/JsonValue"},"default":{}},"scope":{"type":"string","enum":["ORGANIZATION","PROJECT"]},"handle":{"type":"string","pattern":"^[a-z0-9_-]+(?:\\/[a-z0-9_-]+)?$"}},"required":["commitMessage"],"additionalProperties":false}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]},"delete":{"operationId":"deleteApiPromptsById","description":"Delete a prompt","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Prompt not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]}},"/api/prompts/{id}/sync":{"post":{"operationId":"postApiPromptsByIdSync","description":"Sync/upsert a prompt with local content","responses":{"200":{"description":"Sync result","content":{"application/json":{"schema":{"type":"object","properties":{"action":{"type":"string","enum":["created","updated","conflict","up_to_date"]},"prompt":{"type":"object","properties":{"id":{"type":"string"},"handle":{"type":["string","null"]},"scope":{"type":"string","enum":["ORGANIZATION","PROJECT"]},"name":{"type":"string"},"updatedAt":{"type":"string"},"projectId":{"type":"string"},"organizationId":{"type":"string"},"versionId":{"type":"string"},"authorId":{"type":["string","null"]},"version":{"type":"number"},"createdAt":{"type":"string"},"commitMessage":{"type":["string","null"]},"prompt":{"type":"string"},"messages":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string","enum":["user","assistant","system"]},"content":{"type":"string"}},"required":["role","content"]},"default":[]},"inputs":{"type":"array","items":{"type":"object","properties":{"identifier":{"type":"string","minLength":1},"type":{"type":"string","enum":["str","float","bool","image","file","list","list[str]","list[float]","list[int]","list[bool]","dict","chat_messages"]}},"required":["identifier","type"]},"default":[]},"outputs":{"type":"array","items":{"type":"object","properties":{"identifier":{"type":"string","minLength":1},"type":{"type":"string","enum":["str","float","bool","json_schema"]},"json_schema":{"type":"object","properties":{"type":{"type":"string","minLength":1}},"required":["type"],"additionalProperties":true}},"required":["identifier","type"]},"minItems":1},"model":{"type":"string","minLength":1},"temperature":{"type":"number"},"maxTokens":{"type":"number"},"demonstrations":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"inline":{"type":"object","properties":{"records":{"type":"object","additionalProperties":{"type":"array","items":{}}},"columnTypes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"anyOf":[{"type":"string","const":"string"},{"type":"string","const":"boolean"},{"type":"string","const":"number"},{"type":"string","const":"date"},{"type":"string","const":"list"},{"type":"string","const":"json"},{"type":"string","const":"spans"},{"type":"string","const":"rag_contexts"},{"type":"string","const":"chat_messages"},{"type":"string","const":"annotations"},{"type":"string","const":"evaluations"},{"type":"string","const":"image"},{"type":"string","const":"file"}]}},"required":["name","type"]}}},"required":["records","columnTypes"]}}},"promptingTechnique":{"type":"object","properties":{"type":{"type":"string","enum":["few_shot","in_context","chain_of_thought"]},"demonstrations":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"inline":{"type":"object","properties":{"records":{"type":"object","additionalProperties":{"type":"array","items":{}}},"columnTypes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"anyOf":[{"type":"string","const":"string"},{"type":"string","const":"boolean"},{"type":"string","const":"number"},{"type":"string","const":"date"},{"type":"string","const":"list"},{"type":"string","const":"json"},{"type":"string","const":"spans"},{"type":"string","const":"rag_contexts"},{"type":"string","const":"chat_messages"},{"type":"string","const":"annotations"},{"type":"string","const":"evaluations"},{"type":"string","const":"image"},{"type":"string","const":"file"}]}},"required":["name","type"]}}},"required":["records","columnTypes"]}}}},"required":["type"]},"responseFormat":{"type":"object","properties":{"type":{"type":"string","enum":["json_schema"]},"json_schema":{"type":["object","null"],"properties":{"name":{"type":"string"},"schema":{"type":"object","additionalProperties":true}},"required":["name","schema"]}},"required":["type","json_schema"]},"tags":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"versionId":{"type":"string"}},"required":["name","versionId"]},"default":[]},"parameters":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/JsonValue"},"default":{}}},"required":["id","handle","scope","name","updatedAt","projectId","organizationId","versionId","version","createdAt","prompt","outputs","model","messages","inputs","tags","parameters"]},"conflictInfo":{"type":"object","properties":{"localVersion":{"type":"number"},"remoteVersion":{"type":"number"},"differences":{"type":"array","items":{"type":"string"}},"remoteConfigData":{"type":"object","properties":{"prompt":{"type":"string"},"messages":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string","enum":["user","assistant","system"]},"content":{"type":"string"}},"required":["role","content"]},"default":[]},"inputs":{"type":"array","items":{"type":"object","properties":{"identifier":{"type":"string","minLength":1},"type":{"type":"string","enum":["str","float","bool","image","file","list","list[str]","list[float]","list[int]","list[bool]","dict","chat_messages"]}},"required":["identifier","type"]},"default":[]},"outputs":{"type":"array","items":{"type":"object","properties":{"identifier":{"type":"string","minLength":1},"type":{"type":"string","enum":["str","float","bool","json_schema"]},"json_schema":{"type":"object","properties":{"type":{"type":"string","minLength":1}},"required":["type"],"additionalProperties":true}},"required":["identifier","type"]},"minItems":1},"model":{"type":"string","minLength":1},"temperature":{"type":"number"},"max_tokens":{"type":"number"},"top_p":{"type":"number"},"frequency_penalty":{"type":"number"},"presence_penalty":{"type":"number"},"seed":{"type":"number"},"top_k":{"type":"number"},"min_p":{"type":"number"},"repetition_penalty":{"type":"number"},"reasoning":{"type":"string"},"reasoning_effort":{"type":"string"},"thinkingLevel":{"type":"string"},"effort":{"type":"string"},"verbosity":{"type":"string"},"demonstrations":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"inline":{"type":"object","properties":{"records":{"type":"object","additionalProperties":{"type":"array","items":{}}},"columnTypes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"anyOf":[{"type":"string","const":"string"},{"type":"string","const":"boolean"},{"type":"string","const":"number"},{"type":"string","const":"date"},{"type":"string","const":"list"},{"type":"string","const":"json"},{"type":"string","const":"spans"},{"type":"string","const":"rag_contexts"},{"type":"string","const":"chat_messages"},{"type":"string","const":"annotations"},{"type":"string","const":"evaluations"},{"type":"string","const":"image"},{"type":"string","const":"file"}]}},"required":["name","type"]}}},"required":["records","columnTypes"]}}},"prompting_technique":{"type":"object","properties":{"type":{"type":"string","enum":["few_shot","in_context","chain_of_thought"]},"demonstrations":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"inline":{"type":"object","properties":{"records":{"type":"object","additionalProperties":{"type":"array","items":{}}},"columnTypes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"anyOf":[{"type":"string","const":"string"},{"type":"string","const":"boolean"},{"type":"string","const":"number"},{"type":"string","const":"date"},{"type":"string","const":"list"},{"type":"string","const":"json"},{"type":"string","const":"spans"},{"type":"string","const":"rag_contexts"},{"type":"string","const":"chat_messages"},{"type":"string","const":"annotations"},{"type":"string","const":"evaluations"},{"type":"string","const":"image"},{"type":"string","const":"file"}]}},"required":["name","type"]}}},"required":["records","columnTypes"]}}}},"required":["type"]},"response_format":{"type":"object","properties":{"type":{"type":"string","enum":["json_schema"]},"json_schema":{"type":["object","null"],"properties":{"name":{"type":"string"},"schema":{"type":"object","additionalProperties":true}},"required":["name","schema"]}},"required":["type","json_schema"]}},"required":["prompt","outputs","model","messages","inputs"]},"remoteParameters":{"type":"object","additionalProperties":{}}},"required":["localVersion","remoteVersion","differences","remoteConfigData"]}},"required":["action"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"configData":{"type":"object","properties":{"prompt":{"type":"string"},"messages":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string","enum":["user","assistant","system"]},"content":{"type":"string"}},"required":["role","content"]},"default":[]},"inputs":{"type":"array","items":{"type":"object","properties":{"identifier":{"type":"string","minLength":1},"type":{"type":"string","enum":["str","float","bool","image","file","list","list[str]","list[float]","list[int]","list[bool]","dict","chat_messages"]}},"required":["identifier","type"]},"default":[]},"outputs":{"type":"array","items":{"type":"object","properties":{"identifier":{"type":"string","minLength":1},"type":{"type":"string","enum":["str","float","bool","json_schema"]},"json_schema":{"type":"object","properties":{"type":{"type":"string","minLength":1}},"required":["type"],"additionalProperties":true}},"required":["identifier","type"]},"minItems":1},"model":{"type":"string","minLength":1},"temperature":{"type":"number"},"max_tokens":{"type":"number"},"top_p":{"type":"number"},"frequency_penalty":{"type":"number"},"presence_penalty":{"type":"number"},"seed":{"type":"number"},"top_k":{"type":"number"},"min_p":{"type":"number"},"repetition_penalty":{"type":"number"},"reasoning":{"type":"string"},"reasoning_effort":{"type":"string"},"thinkingLevel":{"type":"string"},"effort":{"type":"string"},"verbosity":{"type":"string"},"demonstrations":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"inline":{"type":"object","properties":{"records":{"type":"object","additionalProperties":{"type":"array","items":{}}},"columnTypes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"anyOf":[{"type":"string","const":"string"},{"type":"string","const":"boolean"},{"type":"string","const":"number"},{"type":"string","const":"date"},{"type":"string","const":"list"},{"type":"string","const":"json"},{"type":"string","const":"spans"},{"type":"string","const":"rag_contexts"},{"type":"string","const":"chat_messages"},{"type":"string","const":"annotations"},{"type":"string","const":"evaluations"},{"type":"string","const":"image"},{"type":"string","const":"file"}]}},"required":["name","type"]}}},"required":["records","columnTypes"]}}},"prompting_technique":{"type":"object","properties":{"type":{"type":"string","enum":["few_shot","in_context","chain_of_thought"]},"demonstrations":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"inline":{"type":"object","properties":{"records":{"type":"object","additionalProperties":{"type":"array","items":{}}},"columnTypes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"anyOf":[{"type":"string","const":"string"},{"type":"string","const":"boolean"},{"type":"string","const":"number"},{"type":"string","const":"date"},{"type":"string","const":"list"},{"type":"string","const":"json"},{"type":"string","const":"spans"},{"type":"string","const":"rag_contexts"},{"type":"string","const":"chat_messages"},{"type":"string","const":"annotations"},{"type":"string","const":"evaluations"},{"type":"string","const":"image"},{"type":"string","const":"file"}]}},"required":["name","type"]}}},"required":["records","columnTypes"]}}}},"required":["type"]},"response_format":{"type":"object","properties":{"type":{"type":"string","enum":["json_schema"]},"json_schema":{"type":["object","null"],"properties":{"name":{"type":"string"},"schema":{"type":"object","additionalProperties":true}},"required":["name","schema"]}},"required":["type","json_schema"]}},"required":["prompt","outputs","model"]},"parameters":{"type":"object","additionalProperties":{}},"localVersion":{"type":"number","minimum":0},"commitMessage":{"type":"string"}},"required":["configData"]}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]}},"/api/model-defaults":{"get":{"operationId":"getApiModelDefaults","description":"Snapshot of the default-model cascade for this project: effective resolution per role, plus the configs the caller can read.","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"scope":{"type":"object","properties":{"projectId":{"type":"string"},"teamId":{"type":["string","null"]},"organizationId":{"type":["string","null"]},"organizationName":{"type":["string","null"]}},"required":["projectId","teamId","organizationId","organizationName"]},"effective":{"type":"object","properties":{"DEFAULT":{"type":["object","null"],"properties":{"model":{"type":"string"},"source":{"type":"string"},"scope":{"type":["string","null"]}},"required":["model","source","scope"]},"FAST":{"type":["object","null"],"properties":{"model":{"type":"string"},"source":{"type":"string"},"scope":{"type":["string","null"]}},"required":["model","source","scope"]},"EMBEDDINGS":{"type":["object","null"],"properties":{"model":{"type":"string"},"source":{"type":"string"},"scope":{"type":["string","null"]}},"required":["model","source","scope"]}},"required":["DEFAULT","FAST","EMBEDDINGS"]},"configs":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"config":{"type":"object","additionalProperties":{"type":"string"}},"scopes":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["ORGANIZATION","TEAM","PROJECT"]},"id":{"type":"string"},"name":{"type":"string"}},"required":["type","id","name"]}},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","config","scopes","createdAt","updatedAt"]}}},"required":["scope","effective","configs"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"security":[{"project_api_key":[]}]},"post":{"operationId":"postApiModelDefaults","description":"Create a default-model config attached to one or more scopes. JSON keys may be roles (DEFAULT, FAST, LANGY, EMBEDDINGS) or registered feature keys; missing keys inherit from a higher scope.","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"config":{"type":"object","additionalProperties":{"type":"string"}},"scopes":{"type":"array","items":{"type":"object","properties":{"scopeType":{"type":"string","enum":["ORGANIZATION","TEAM","PROJECT"]},"scopeId":{"type":"string","minLength":1}},"required":["scopeType","scopeId"]},"minItems":1}},"required":["config","scopes"]}}}},"security":[{"project_api_key":[]}]}},"/api/model-defaults/{id}":{"put":{"operationId":"putApiModelDefaultsById","description":"Update a config's JSON payload and/or its scope attachments. Sending `scopes: []` deletes the config.","responses":{"204":{"description":"Updated"},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"config":{"type":"object","additionalProperties":{"type":"string"}},"scopes":{"type":"array","items":{"type":"object","properties":{"scopeType":{"type":"string","enum":["ORGANIZATION","TEAM","PROJECT"]},"scopeId":{"type":"string","minLength":1}},"required":["scopeType","scopeId"]}}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]},"delete":{"operationId":"deleteApiModelDefaultsById","description":"Delete a default-model config. Scope attachments cascade.","responses":{"204":{"description":"Deleted"},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]}},"/api/model-providers":{"get":{"operationId":"getApiModelProviders","description":"List all model providers for a project with masked API keys","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"object","properties":{"id":{"type":"string"},"provider":{"type":"string"},"enabled":{"type":"boolean"},"customKeys":{"type":["object","null"],"additionalProperties":{}},"deploymentMapping":{"type":"null"},"models":{"type":["array","null"],"items":{"type":"string"}},"embeddingsModels":{"type":["array","null"],"items":{"type":"string"}},"customModels":{"type":["array","null"],"items":{"type":"object","properties":{"modelId":{"type":"string","minLength":1},"displayName":{"type":"string","minLength":1},"mode":{"type":"string","enum":["chat","embedding"]},"maxTokens":{"type":["number","null"],"exclusiveMinimum":0},"supportedParameters":{"type":"array","items":{"type":"string","enum":["temperature","max_tokens","top_p","frequency_penalty","presence_penalty","top_k","min_p","repetition_penalty","seed","reasoning","verbosity"]}},"multimodalInputs":{"type":"array","items":{"type":"string","enum":["image","file","audio"]}}},"required":["modelId","displayName","mode"]}},"customEmbeddingsModels":{"type":["array","null"],"items":{"type":"object","properties":{"modelId":{"type":"string","minLength":1},"displayName":{"type":"string","minLength":1},"mode":{"type":"string","enum":["chat","embedding"]},"maxTokens":{"type":["number","null"],"exclusiveMinimum":0},"supportedParameters":{"type":"array","items":{"type":"string","enum":["temperature","max_tokens","top_p","frequency_penalty","presence_penalty","top_k","min_p","repetition_penalty","seed","reasoning","verbosity"]}},"multimodalInputs":{"type":"array","items":{"type":"string","enum":["image","file","audio"]}}},"required":["modelId","displayName","mode"]}},"disabledByDefault":{"type":"boolean"},"extraHeaders":{"type":["array","null"],"items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":"string"}},"required":["key","value"]}}},"required":["provider","enabled","customKeys"]}}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"security":[{"project_api_key":[]}]}},"/api/model-providers/{provider}":{"put":{"operationId":"putApiModelProvidersByProvider","description":"Create or update a model provider","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"object","properties":{"id":{"type":"string"},"provider":{"type":"string"},"enabled":{"type":"boolean"},"customKeys":{"type":["object","null"],"additionalProperties":{}},"deploymentMapping":{"type":"null"},"models":{"type":["array","null"],"items":{"type":"string"}},"embeddingsModels":{"type":["array","null"],"items":{"type":"string"}},"customModels":{"type":["array","null"],"items":{"type":"object","properties":{"modelId":{"type":"string","minLength":1},"displayName":{"type":"string","minLength":1},"mode":{"type":"string","enum":["chat","embedding"]},"maxTokens":{"type":["number","null"],"exclusiveMinimum":0},"supportedParameters":{"type":"array","items":{"type":"string","enum":["temperature","max_tokens","top_p","frequency_penalty","presence_penalty","top_k","min_p","repetition_penalty","seed","reasoning","verbosity"]}},"multimodalInputs":{"type":"array","items":{"type":"string","enum":["image","file","audio"]}}},"required":["modelId","displayName","mode"]}},"customEmbeddingsModels":{"type":["array","null"],"items":{"type":"object","properties":{"modelId":{"type":"string","minLength":1},"displayName":{"type":"string","minLength":1},"mode":{"type":"string","enum":["chat","embedding"]},"maxTokens":{"type":["number","null"],"exclusiveMinimum":0},"supportedParameters":{"type":"array","items":{"type":"string","enum":["temperature","max_tokens","top_p","frequency_penalty","presence_penalty","top_k","min_p","repetition_penalty","seed","reasoning","verbosity"]}},"multimodalInputs":{"type":"array","items":{"type":"string","enum":["image","file","audio"]}}},"required":["modelId","displayName","mode"]}},"disabledByDefault":{"type":"boolean"},"extraHeaders":{"type":["array","null"],"items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":"string"}},"required":["key","value"]}}},"required":["provider","enabled","customKeys"]}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"enabled":{"type":"boolean"},"customKeys":{"type":"object","additionalProperties":{}},"customModels":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"modelId":{"type":"string","minLength":1},"displayName":{"type":"string","minLength":1},"mode":{"type":"string","enum":["chat","embedding"]},"maxTokens":{"type":["number","null"],"exclusiveMinimum":0},"supportedParameters":{"type":"array","items":{"type":"string","enum":["temperature","max_tokens","top_p","frequency_penalty","presence_penalty","top_k","min_p","repetition_penalty","seed","reasoning","verbosity"]}},"multimodalInputs":{"type":"array","items":{"type":"string","enum":["image","file","audio"]}}},"required":["modelId","displayName","mode"]}},{"type":"array","items":{"type":"string"}}]},"customEmbeddingsModels":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"modelId":{"type":"string","minLength":1},"displayName":{"type":"string","minLength":1},"mode":{"type":"string","enum":["chat","embedding"]},"maxTokens":{"type":["number","null"],"exclusiveMinimum":0},"supportedParameters":{"type":"array","items":{"type":"string","enum":["temperature","max_tokens","top_p","frequency_penalty","presence_penalty","top_k","min_p","repetition_penalty","seed","reasoning","verbosity"]}},"multimodalInputs":{"type":"array","items":{"type":"string","enum":["image","file","audio"]}}},"required":["modelId","displayName","mode"]}},{"type":"array","items":{"type":"string"}}]},"extraHeaders":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":"string"}},"required":["key","value"]}},"defaultModel":{"type":"string"}},"required":["enabled"]}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"provider","required":true}],"security":[{"project_api_key":[]}]}},"/api/monitors":{"get":{"operationId":"getApiMonitors","description":"List all online evaluation monitors for the project","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"checkType":{"type":"string"},"enabled":{"type":"boolean"},"executionMode":{"type":"string","enum":["ON_MESSAGE","AS_GUARDRAIL","MANUALLY"]},"sample":{"type":"number"},"level":{"type":"string"},"evaluatorId":{"type":["string","null"]},"preconditions":{},"parameters":{},"mappings":{"type":"null"},"threadIdleTimeout":{"type":["number","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"platformUrl":{"type":"string","format":"uri"}},"required":["id","name","slug","checkType","enabled","executionMode","sample","level","evaluatorId","threadIdleTimeout","createdAt","updatedAt","platformUrl"]}}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"security":[{"project_api_key":[]}]},"post":{"operationId":"postApiMonitors","description":"Create a new online evaluation monitor","responses":{"201":{"description":"Monitor created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"checkType":{"type":"string"},"enabled":{"type":"boolean"},"executionMode":{"type":"string","enum":["ON_MESSAGE","AS_GUARDRAIL","MANUALLY"]},"sample":{"type":"number"},"level":{"type":"string"},"evaluatorId":{"type":["string","null"]},"preconditions":{},"parameters":{},"mappings":{"type":"null"},"threadIdleTimeout":{"type":["number","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"platformUrl":{"type":"string","format":"uri"}},"required":["id","name","slug","checkType","enabled","executionMode","sample","level","evaluatorId","threadIdleTimeout","createdAt","updatedAt","platformUrl"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1},"checkType":{"type":"string","minLength":1},"executionMode":{"type":"string","enum":["ON_MESSAGE","AS_GUARDRAIL","MANUALLY"],"default":"ON_MESSAGE"},"preconditions":{"type":"array","items":{},"default":[]},"parameters":{"type":"object","additionalProperties":{},"default":{}},"mappings":{"type":["object","null"],"properties":{"mapping":{"type":"object","additionalProperties":{"anyOf":[{"type":"object","properties":{"source":{"anyOf":[{"type":"string","enum":["trace_id","thread_id","timestamp","input","output","contexts","contexts.string_list","metrics.total_cost","metrics.first_token_ms","metrics.total_time_ms","metrics.prompt_tokens","metrics.completion_tokens","metrics.total_tokens","spans","spans.llm.input","spans.llm.output","metadata","evaluations","annotations","events","threads","threads_until_current","formatted_trace"]},{"type":"string","const":""}]},"key":{"type":"string"},"subkey":{"type":"string"},"selectedFields":{"type":"array","items":{"type":"string"}},"type":{"type":"string","const":"trace"}},"required":["source"]},{"type":"object","properties":{"source":{"anyOf":[{"type":"string","enum":["thread_id","traces","formatted_traces"]},{"type":"string","const":""}]},"key":{"type":"string"},"subkey":{"type":"string"},"selectedFields":{"type":"array","items":{"type":"string"}},"type":{"type":"string","const":"thread"}},"required":["source","type"]}]}},"expansions":{"type":"array","items":{"type":"string","enum":["spans.llm.span_id","spans.all.span_id","annotations.id","events.event_id"]}}},"required":["mapping","expansions"]},"sample":{"type":"number","minimum":0,"maximum":1,"default":1},"evaluatorId":{"type":"string","minLength":1},"level":{"type":"string","enum":["trace","thread"],"default":"trace"},"threadIdleTimeout":{"type":["integer","null"],"exclusiveMinimum":0}},"required":["name","checkType"]}}}},"security":[{"project_api_key":[]}]}},"/api/monitors/{id}":{"get":{"operationId":"getApiMonitorsById","description":"Get a monitor by its ID","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"checkType":{"type":"string"},"enabled":{"type":"boolean"},"executionMode":{"type":"string","enum":["ON_MESSAGE","AS_GUARDRAIL","MANUALLY"]},"sample":{"type":"number"},"level":{"type":"string"},"evaluatorId":{"type":["string","null"]},"preconditions":{},"parameters":{},"mappings":{"type":"null"},"threadIdleTimeout":{"type":["number","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"platformUrl":{"type":"string","format":"uri"}},"required":["id","name","slug","checkType","enabled","executionMode","sample","level","evaluatorId","threadIdleTimeout","createdAt","updatedAt","platformUrl"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Monitor not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]},"patch":{"operationId":"patchApiMonitorsById","description":"Update a monitor (name, enabled state, settings, etc.)","responses":{"200":{"description":"Monitor updated","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"checkType":{"type":"string"},"enabled":{"type":"boolean"},"executionMode":{"type":"string","enum":["ON_MESSAGE","AS_GUARDRAIL","MANUALLY"]},"sample":{"type":"number"},"level":{"type":"string"},"evaluatorId":{"type":["string","null"]},"preconditions":{},"parameters":{},"mappings":{"type":"null"},"threadIdleTimeout":{"type":["number","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"platformUrl":{"type":"string","format":"uri"}},"required":["id","name","slug","checkType","enabled","executionMode","sample","level","evaluatorId","threadIdleTimeout","createdAt","updatedAt","platformUrl"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Monitor not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1},"enabled":{"type":"boolean"},"checkType":{"type":"string"},"executionMode":{"type":"string","enum":["ON_MESSAGE","AS_GUARDRAIL","MANUALLY"]},"preconditions":{"type":"array","items":{}},"parameters":{"type":"object","additionalProperties":{}},"mappings":{"type":["object","null"],"properties":{"mapping":{"type":"object","additionalProperties":{"anyOf":[{"type":"object","properties":{"source":{"anyOf":[{"type":"string","enum":["trace_id","thread_id","timestamp","input","output","contexts","contexts.string_list","metrics.total_cost","metrics.first_token_ms","metrics.total_time_ms","metrics.prompt_tokens","metrics.completion_tokens","metrics.total_tokens","spans","spans.llm.input","spans.llm.output","metadata","evaluations","annotations","events","threads","threads_until_current","formatted_trace"]},{"type":"string","const":""}]},"key":{"type":"string"},"subkey":{"type":"string"},"selectedFields":{"type":"array","items":{"type":"string"}},"type":{"type":"string","const":"trace"}},"required":["source"]},{"type":"object","properties":{"source":{"anyOf":[{"type":"string","enum":["thread_id","traces","formatted_traces"]},{"type":"string","const":""}]},"key":{"type":"string"},"subkey":{"type":"string"},"selectedFields":{"type":"array","items":{"type":"string"}},"type":{"type":"string","const":"thread"}},"required":["source","type"]}]}},"expansions":{"type":"array","items":{"type":"string","enum":["spans.llm.span_id","spans.all.span_id","annotations.id","events.event_id"]}}},"required":["mapping","expansions"]},"sample":{"type":"number","minimum":0,"maximum":1},"evaluatorId":{"type":["string","null"],"minLength":1},"level":{"type":"string","enum":["trace","thread"]},"threadIdleTimeout":{"type":["integer","null"],"exclusiveMinimum":0}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]},"delete":{"operationId":"deleteApiMonitorsById","description":"Delete a monitor","responses":{"200":{"description":"Monitor deleted","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"deleted":{"type":"boolean"}},"required":["id","deleted"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Monitor not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]}},"/api/monitors/{id}/toggle":{"post":{"operationId":"postApiMonitorsByIdToggle","description":"Enable or disable a monitor","responses":{"200":{"description":"Monitor toggled","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"enabled":{"type":"boolean"}},"required":["id","enabled"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Monitor not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"enabled":{"type":"boolean"}},"required":["enabled"]}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]}},"/api/organization":{"get":{"operationId":"getOrganization","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"supportContact":{"type":["string","null"]},"presenceEnabled":{"type":"boolean"},"traceSharingEnabled":{"type":"boolean"},"primaryIntent":{"type":["string","null"],"enum":["AGENT_GOVERNANCE","LLM_OPS",null]},"s3Endpoint":{"type":["string","null"]},"s3AccessKeyId":{"type":["string","null"]},"s3Bucket":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","name","slug","supportContact","presenceEnabled","traceSharingEnabled","primaryIntent","s3Endpoint","s3AccessKeyId","s3Bucket","createdAt","updatedAt"]}}}}},"description":"Read the organization profile: name, slug, support contact, presence and trace sharing settings, and the S3 storage shape. The single sign-on fields and the S3 secret are never returned.","tags":["Organization"],"security":[{"admin_api_key":[]}]},"patch":{"operationId":"updateOrganization","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"supportContact":{"type":["string","null"]},"presenceEnabled":{"type":"boolean"},"traceSharingEnabled":{"type":"boolean"},"primaryIntent":{"type":["string","null"],"enum":["AGENT_GOVERNANCE","LLM_OPS",null]},"s3Endpoint":{"type":["string","null"]},"s3AccessKeyId":{"type":["string","null"]},"s3Bucket":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","name","slug","supportContact","presenceEnabled","traceSharingEnabled","primaryIntent","s3Endpoint","s3AccessKeyId","s3Bucket","createdAt","updatedAt"]}}}}},"description":"Update the organization profile. Partial: only the fields present are written, and the response is exactly what a subsequent GET returns.","tags":["Organization"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"supportContact":{"type":["string","null"],"maxLength":255},"presenceEnabled":{"type":"boolean"},"traceSharingEnabled":{"type":"boolean"},"primaryIntent":{"type":["string","null"],"enum":["AGENT_GOVERNANCE","LLM_OPS",null]},"s3Endpoint":{"type":["string","null"],"maxLength":2048},"s3AccessKeyId":{"type":["string","null"],"maxLength":1024},"s3SecretAccessKey":{"type":["string","null"],"maxLength":1024},"s3Bucket":{"type":["string","null"],"maxLength":1024}}}}}},"security":[{"admin_api_key":[]}]}},"/api/organization/members":{"get":{"operationId":"listOrganizationMembers","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"members":{"type":"array","items":{"type":"object","properties":{"userId":{"type":"string"},"role":{"type":"string","enum":["ADMIN","MEMBER","EXTERNAL","DEVELOPER"]},"disabled":{"type":"boolean"},"disabledAt":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"user":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":["string","null"]},"email":{"type":["string","null"]}},"required":["id","name","email"]}},"required":["userId","role","disabled","disabledAt","createdAt","updatedAt","user"]}},"totalCount":{"type":"number"}},"required":["members","totalCount"]}}}}},"description":"List the organization's members with their organization role and disabled status. Disabled members are included only when includeDisabled=true.","tags":["Members"],"parameters":[{"in":"query","name":"includeDisabled","schema":{"type":"string","enum":["true","false"]}},{"in":"query","name":"offset","schema":{"type":"integer","minimum":0}},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":200}}],"security":[{"admin_api_key":[]}]}},"/api/organization/members/{userId}":{"get":{"operationId":"getOrganizationMember","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"userId":{"type":"string"},"role":{"type":"string","enum":["ADMIN","MEMBER","EXTERNAL","DEVELOPER"]},"disabled":{"type":"boolean"},"disabledAt":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"user":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":["string","null"]},"email":{"type":["string","null"]}},"required":["id","name","email"]},"teams":{"type":"array","items":{"type":"object","properties":{"teamId":{"type":"string"},"teamName":{"type":"string"},"role":{"type":"string","enum":["ADMIN","MEMBER","VIEWER","CUSTOM"]},"customRoleId":{"type":["string","null"]},"customRoleName":{"type":["string","null"]}},"required":["teamId","teamName","role","customRoleId","customRoleName"]}}},"required":["userId","role","disabled","disabledAt","createdAt","updatedAt","user","teams"]}}}}},"description":"Read one member, including the teams they reach through team-scoped role bindings. Personal workspaces are not listed: they are not access an administrator manages.","tags":["Members"],"parameters":[{"in":"path","name":"userId","schema":{"type":"string","minLength":1},"required":true}],"security":[{"admin_api_key":[]}]},"patch":{"operationId":"updateOrganizationMember","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"userId":{"type":"string"},"role":{"type":"string","enum":["ADMIN","MEMBER","EXTERNAL","DEVELOPER"]},"disabled":{"type":"boolean"},"disabledAt":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"user":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":["string","null"]},"email":{"type":["string","null"]}},"required":["id","name","email"]},"teamsLeftWithoutAdmin":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"]}}},"required":["userId","role","disabled","disabledAt","createdAt","updatedAt","user"]}}}}},"description":"Change a member's organization role, or disable / re-enable their membership. Send exactly one of role or disabled. Re-enabling consumes a seat, so it is checked against the plan.","tags":["Members"],"parameters":[{"in":"path","name":"userId","schema":{"type":"string","minLength":1},"required":true}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"role":{"type":"string","enum":["ADMIN","MEMBER","EXTERNAL","DEVELOPER"]},"disabled":{"type":"boolean"}}}}}},"security":[{"admin_api_key":[]}]},"delete":{"operationId":"removeOrganizationMember","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true}},"required":["success"]}}}}},"description":"Remove a member from the organization and every team in it. The member the credential acts as cannot remove themselves.","tags":["Members"],"parameters":[{"in":"path","name":"userId","schema":{"type":"string","minLength":1},"required":true}],"security":[{"admin_api_key":[]}]}},"/api/organization/members/{userId}/access":{"get":{"operationId":"getOrganizationMemberAccess","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"user":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":["string","null"]},"email":{"type":["string","null"]},"orgRole":{"type":"string"},"orgRolePermissions":{"type":"array","items":{"type":"string"}}},"required":["id","name","email","orgRole","orgRolePermissions"]},"groups":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"scimSource":{"type":["string","null"]},"bindings":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"role":{"type":"string"},"customRoleName":{"type":["string","null"]},"scopeType":{"type":"string","enum":["ORGANIZATION","TEAM","PROJECT"]},"scopeId":{"type":"string"},"scopeName":{"type":["string","null"]},"permissions":{"type":"array","items":{"type":"string"}}},"required":["id","role","customRoleName","scopeType","scopeId","scopeName","permissions"]}}},"required":["id","name","slug","scimSource","bindings"]}},"directBindings":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"role":{"type":"string"},"customRoleName":{"type":["string","null"]},"scopeType":{"type":"string","enum":["ORGANIZATION","TEAM","PROJECT"]},"scopeId":{"type":"string"},"scopeName":{"type":["string","null"]},"permissions":{"type":"array","items":{"type":"string"}}},"required":["id","role","customRoleName","scopeType","scopeId","scopeName","permissions"]}}},"required":["user","groups","directBindings"]}}}}},"description":"The member's full access breakdown: organization role, group memberships with their bindings, and direct bindings, each with the permissions it grants and the scope it grants them on.","tags":["Members"],"parameters":[{"in":"path","name":"userId","schema":{"type":"string","minLength":1},"required":true}],"security":[{"admin_api_key":[]}]}},"/api/organization/invites":{"get":{"operationId":"listOrganizationInvites","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"invites":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"role":{"type":"string","enum":["ADMIN","MEMBER","EXTERNAL","DEVELOPER"]},"status":{"type":"string"},"expiration":{"type":["string","null"]},"inviteCode":{"type":"string"},"inviteUrl":{"type":"string"},"teams":{"type":"array","items":{"type":"object","properties":{"teamId":{"type":"string"},"role":{"type":"string"},"customRoleId":{"type":["string","null"]}},"required":["teamId","role","customRoleId"]}},"createdAt":{"type":"string"}},"required":["id","email","role","status","expiration","inviteCode","inviteUrl","teams","createdAt"]}}},"required":["invites"]}}}}},"description":"List pending invites. Each carries its invite code and acceptance link, because a provisioning run with no email provider still has to hand the person something to open.","tags":["Invites"],"security":[{"admin_api_key":[]}]},"post":{"operationId":"createOrganizationInvites","responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"invites":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"role":{"type":"string","enum":["ADMIN","MEMBER","EXTERNAL","DEVELOPER"]},"status":{"type":"string"},"expiration":{"type":["string","null"]},"inviteCode":{"type":"string"},"inviteUrl":{"type":"string"},"teams":{"type":"array","items":{"type":"object","properties":{"teamId":{"type":"string"},"role":{"type":"string"},"customRoleId":{"type":["string","null"]}},"required":["teamId","role","customRoleId"]}},"createdAt":{"type":"string"},"emailNotSent":{"type":"boolean"}},"required":["id","email","role","status","expiration","inviteCode","inviteUrl","teams","createdAt","emailNotSent"]}}},"required":["invites"]}}}}},"description":"Create up to 50 invites in one batch, each with team assignments that may carry a custom role. Validation is strict: a team or custom role that cannot be assigned refuses the batch rather than silently granting less than was asked. emailNotSent reports, per invite, whether the invite email could be delivered.","tags":["Invites"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"invites":{"type":"array","items":{"type":"object","properties":{"email":{"type":"string","format":"email","minLength":1},"role":{"type":"string","enum":["ADMIN","MEMBER","EXTERNAL","DEVELOPER"]},"teams":{"type":"array","items":{"type":"object","properties":{"teamId":{"type":"string","minLength":1},"role":{"type":"string","enum":["ADMIN","MEMBER","VIEWER","CUSTOM"]},"customRoleId":{"type":"string","minLength":1}},"required":["teamId","role"]},"minItems":1}},"required":["email","role","teams"]},"minItems":1,"maxItems":50}},"required":["invites"]}}}},"security":[{"admin_api_key":[]}]}},"/api/organization/invites/{id}":{"delete":{"operationId":"revokeOrganizationInvite","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true}},"required":["success"]}}}}},"description":"Revoke a pending invite. An invite id from another organization, or one already revoked, answers 404.","tags":["Invites"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1},"required":true}],"security":[{"admin_api_key":[]}]}},"/api/organizations":{"post":{"operationId":"provisionOrganization","summary":"Create an organization","description":"Self-hosted only. Creates an organization with a default team and returns an organization-scoped admin API key, so provisioning can continue through the management APIs without a browser step: the instance key creates the organization, the returned key does everything else. The slug is the natural key; a taken slug answers 409 organization_slug_taken.","tags":["Organizations (Self-Hosted)"],"security":[{"instance_admin_key":[]}],"responses":{"201":{"description":"Organization created. adminApiKey.token is the bootstrap credential and is only shown once.","content":{"application/json":{"schema":{"type":"object","properties":{"organization":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"}}},"team":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"}}},"adminApiKey":{"type":"object","properties":{"id":{"type":"string"},"token":{"type":"string","description":"Plaintext organization admin API key (sk-lw-...). Store securely: shown only once."}}}}}}}},"401":{"description":"Invalid instance administrator credential","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable machine-readable code, e.g. organization_slug_taken"},"message":{"type":"string"}}}}}},"404":{"description":"Organization provisioning is not available: the instance administrator key is not configured, this is a cloud deployment, or (on GET /{id}) the organization does not exist","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable machine-readable code, e.g. organization_slug_taken"},"message":{"type":"string"}}}}}},"409":{"description":"An organization with this slug already exists (organization_slug_taken)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable machine-readable code, e.g. organization_slug_taken"},"message":{"type":"string"}}}}}},"422":{"description":"The request body did not match the schema, for example a slug that is not lowercase letters, numbers and single hyphens","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable machine-readable code, e.g. organization_slug_taken"},"message":{"type":"string"}}}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"slug":{"type":"string","pattern":"^[a-z0-9]+(?:-[a-z0-9]+)*$","minLength":1,"maxLength":255},"adminApiKeyName":{"type":"string","minLength":1,"maxLength":100}},"required":["name"]}}}}},"get":{"operationId":"listOrganizations","summary":"List organizations","description":"Self-hosted only. Lists every organization on this instance, newest first.","tags":["Organizations (Self-Hosted)"],"security":[{"instance_admin_key":[]}],"responses":{"200":{"description":"Organizations on this instance","content":{"application/json":{"schema":{"type":"object","properties":{"organizations":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}}}}}}}}},"401":{"description":"Invalid instance administrator credential","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable machine-readable code, e.g. organization_slug_taken"},"message":{"type":"string"}}}}}},"404":{"description":"Organization provisioning is not available: the instance administrator key is not configured, this is a cloud deployment, or (on GET /{id}) the organization does not exist","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable machine-readable code, e.g. organization_slug_taken"},"message":{"type":"string"}}}}}}}}},"/api/organizations/{id}":{"get":{"operationId":"getOrganizationById","summary":"Get an organization","description":"Self-hosted only. Reads one organization's summary by id.","tags":["Organizations (Self-Hosted)"],"security":[{"instance_admin_key":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Organization ID"}],"responses":{"200":{"description":"The organization","content":{"application/json":{"schema":{"type":"object","properties":{"organization":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}}}}}}}},"401":{"description":"Invalid instance administrator credential","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable machine-readable code, e.g. organization_slug_taken"},"message":{"type":"string"}}}}}},"404":{"description":"Organization provisioning is not available: the instance administrator key is not configured, this is a cloud deployment, or (on GET /{id}) the organization does not exist","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable machine-readable code, e.g. organization_slug_taken"},"message":{"type":"string"}}}}}}}}},"/api/role-bindings":{"get":{"operationId":"listRoleBindings","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"bindings":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"principal":{"type":"object","properties":{"type":{"type":"string","enum":["user","group","apiKey"]},"id":{"type":"string"},"name":{"type":["string","null"]}},"required":["type","id","name"]},"role":{"type":"string","enum":["ADMIN","MEMBER","VIEWER","CUSTOM"]},"customRoleId":{"type":["string","null"]},"customRoleName":{"type":["string","null"]},"scopeType":{"type":"string","enum":["ORGANIZATION","TEAM","PROJECT"]},"scopeId":{"type":"string"},"scopeName":{"type":["string","null"]},"createdAt":{"type":"string"}},"required":["id","principal","role","customRoleId","customRoleName","scopeType","scopeId","scopeName","createdAt"]}},"totalCount":{"type":"number"}},"required":["bindings","totalCount"]}}}}},"description":"List the organization's role bindings, each naming its principal (user, group or API key), role and scope. Filter by principal or scope; totalCount counts the filtered set.","tags":["Role Bindings"],"parameters":[{"in":"query","name":"userId","schema":{"type":"string","minLength":1}},{"in":"query","name":"groupId","schema":{"type":"string","minLength":1}},{"in":"query","name":"apiKeyId","schema":{"type":"string","minLength":1}},{"in":"query","name":"scopeType","schema":{"type":"string","enum":["ORGANIZATION","TEAM","PROJECT"]}},{"in":"query","name":"scopeId","schema":{"type":"string","minLength":1}},{"in":"query","name":"offset","schema":{"type":"integer","minimum":0}},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":200}}],"security":[{"admin_api_key":[]}]},"post":{"operationId":"createRoleBinding","responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"principal":{"type":"object","properties":{"type":{"type":"string","enum":["user","group","apiKey"]},"id":{"type":"string"},"name":{"type":["string","null"]}},"required":["type","id","name"]},"role":{"type":"string","enum":["ADMIN","MEMBER","VIEWER","CUSTOM"]},"customRoleId":{"type":["string","null"]},"customRoleName":{"type":["string","null"]},"scopeType":{"type":"string","enum":["ORGANIZATION","TEAM","PROJECT"]},"scopeId":{"type":"string"},"scopeName":{"type":["string","null"]},"createdAt":{"type":"string"}},"required":["id","principal","role","customRoleId","customRoleName","scopeType","scopeId","scopeName","createdAt"]}}}}},"description":"Create a role binding for exactly one principal: a user, a group, or an API key. Every reference is checked against the caller's organization, and an identical binding answers 409 role_binding_already_exists. The response always carries the new binding's id; the names of its principal, role and scope may be absent on this response alone, and a follow-up read carries them.","tags":["Role Bindings"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"userId":{"type":"string","minLength":1},"groupId":{"type":"string","minLength":1},"apiKeyId":{"type":"string","minLength":1},"role":{"type":"string","enum":["ADMIN","MEMBER","VIEWER","CUSTOM"]},"customRoleId":{"type":"string","minLength":1},"scopeType":{"type":"string","enum":["ORGANIZATION","TEAM","PROJECT"]},"scopeId":{"type":"string","minLength":1}},"required":["role","scopeType","scopeId"]}}}},"security":[{"admin_api_key":[]}]}},"/api/role-bindings/{id}":{"patch":{"operationId":"updateRoleBinding","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"principal":{"type":"object","properties":{"type":{"type":"string","enum":["user","group","apiKey"]},"id":{"type":"string"},"name":{"type":["string","null"]}},"required":["type","id","name"]},"role":{"type":"string","enum":["ADMIN","MEMBER","VIEWER","CUSTOM"]},"customRoleId":{"type":["string","null"]},"customRoleName":{"type":["string","null"]},"scopeType":{"type":"string","enum":["ORGANIZATION","TEAM","PROJECT"]},"scopeId":{"type":"string"},"scopeName":{"type":["string","null"]},"createdAt":{"type":"string"}},"required":["id","principal","role","customRoleId","customRoleName","scopeType","scopeId","scopeName","createdAt"]}}}}},"description":"Change a binding's role (and custom role). The principal and scope are the binding's identity and do not change; create a new binding instead.","tags":["Role Bindings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1},"required":true}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"role":{"type":"string","enum":["ADMIN","MEMBER","VIEWER","CUSTOM"]},"customRoleId":{"type":"string","minLength":1}},"required":["role"]}}}},"security":[{"admin_api_key":[]}]},"delete":{"operationId":"deleteRoleBinding","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true}},"required":["success"]}}}}},"description":"Delete a role binding. An id that does not exist in the caller's organization answers 404 role_binding_not_found.","tags":["Role Bindings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1},"required":true}],"security":[{"admin_api_key":[]}]}},"/api/roles":{"get":{"operationId":"listRoles","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"roles":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"permissions":{"type":"array","items":{"type":"string"}},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","name","description","permissions","createdAt","updatedAt"]}}},"required":["roles"]}}}}},"description":"List the organization's custom roles with their permission sets.","tags":["Roles"],"security":[{"admin_api_key":[]}]},"post":{"operationId":"createRole","responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"permissions":{"type":"array","items":{"type":"string"}},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","name","description","permissions","createdAt","updatedAt"]}}}}},"description":"Create a custom role from resource:action permission keys. The name is unique within the organization; a taken name answers 409 custom_role_name_taken.","tags":["Roles"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100},"description":{"type":"string","maxLength":500},"permissions":{"type":"array","items":{"type":"string"},"minItems":1}},"required":["name","permissions"]}}}},"security":[{"admin_api_key":[]}]}},"/api/roles/permissions":{"get":{"operationId":"listRolePermissions","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"resources":{"type":"array","items":{"type":"object","properties":{"resource":{"type":"string"},"organizationExclusive":{"type":"boolean"},"actions":{"type":"array","items":{"type":"string"}},"permissions":{"type":"array","items":{"type":"string"}}},"required":["resource","organizationExclusive","actions","permissions"]}},"actions":{"type":"array","items":{"type":"string"}}},"required":["resources","actions"]}}}}},"description":"The permission catalog custom roles are built from: every resource with its actions, annotated with whether the resource only takes effect at organization scope (such a permission cannot be granted by a team- or project-scoped binding).","tags":["Roles"],"security":[{"admin_api_key":[]}]}},"/api/roles/{id}":{"get":{"operationId":"getRole","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"permissions":{"type":"array","items":{"type":"string"}},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","name","description","permissions","createdAt","updatedAt"]}}}}},"description":"Read one custom role. An id from another organization answers 404 custom_role_not_found.","tags":["Roles"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1},"required":true}],"security":[{"admin_api_key":[]}]},"patch":{"operationId":"updateRole","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"permissions":{"type":"array","items":{"type":"string"}},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","name","description","permissions","createdAt","updatedAt"]}}}}},"description":"Update a custom role. Partial: only the fields present are written; a permissions list replaces the set outright.","tags":["Roles"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1},"required":true}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100},"description":{"type":["string","null"],"maxLength":500},"permissions":{"type":"array","items":{"type":"string"},"minItems":1}}}}}},"security":[{"admin_api_key":[]}]},"delete":{"operationId":"deleteRole","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true}},"required":["success"]}}}}},"description":"Delete a custom role. A role that anything still holds, a legacy team assignment or a role binding, answers 409 custom_role_in_use with the counts in meta.","tags":["Roles"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1},"required":true}],"security":[{"admin_api_key":[]}]}},"/api/scim-tokens":{"get":{"operationId":"listScimTokens","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"tokens":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"description":{"type":["string","null"]},"connectionId":{"type":["string","null"]},"createdAt":{"type":"string"},"lastUsedAt":{"type":["string","null"]}},"required":["id","description","connectionId","createdAt","lastUsedAt"]}}},"required":["tokens"]}}}}},"description":"List the organization's SCIM bearer tokens: id, description, the connection each one manages, creation time and last use. Token values and hashes are never returned; the value exists only in the create response, once.","tags":["SCIM Tokens"],"security":[{"admin_api_key":[]}]},"post":{"operationId":"createScimToken","responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"token":{"type":"string"},"connectionId":{"type":"string"},"description":{"type":["string","null"]}},"required":["id","token","connectionId","description"]}}}}},"description":"Mint a SCIM bearer token for one of this organization's single sign-on connections, for use against /api/scim/v2. The token only manages the people that connection provisioned. The token value is returned once, here, and never again; store it in the identity provider immediately.","tags":["SCIM Tokens"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"description":{"type":"string","minLength":1,"maxLength":255},"connectionId":{"type":"string","minLength":1}}}}}},"security":[{"admin_api_key":[]}]}},"/api/scim-tokens/{id}":{"delete":{"operationId":"revokeScimToken","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true}},"required":["success"]}}}}},"description":"Revoke a SCIM token so it stops verifying immediately. An unknown or already-revoked id answers 404 scim_token_not_found.","tags":["SCIM Tokens"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1},"required":true}],"security":[{"admin_api_key":[]}]}},"/api/scim/v2/ServiceProviderConfig":{"get":{"operationId":"scimGetServiceProviderConfig","summary":"Get the SCIM service provider configuration","description":"What this SCIM implementation supports (RFC 7643 section 5), which is how an identity provider decides what it may call: PATCH and filtering are supported, bulk operations, sorting, ETags and password change are not. Unauthenticated, because a provider reads it while being configured, before a token exists.","tags":["SCIM"],"security":[],"responses":{"200":{"description":"The supported capabilities.","content":{"application/json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"documentationUri":{"type":"string"},"patch":{"type":"object","properties":{"supported":{"type":"boolean"}}},"bulk":{"type":"object","properties":{"supported":{"type":"boolean"},"maxOperations":{"type":"integer"},"maxPayloadSize":{"type":"integer"}}},"filter":{"type":"object","properties":{"supported":{"type":"boolean"},"maxResults":{"type":"integer"}}},"changePassword":{"type":"object","properties":{"supported":{"type":"boolean"}}},"sort":{"type":"object","properties":{"supported":{"type":"boolean"}}},"etag":{"type":"object","properties":{"supported":{"type":"boolean"}}},"authenticationSchemes":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"}}}}}}}}}}}},"/api/scim/v2/ResourceTypes":{"get":{"operationId":"scimListResourceTypes","summary":"List the SCIM resource types","description":"The resources this service provisions, User and Group, each naming the endpoint and the schema URN that serves it (RFC 7643 section 6). Unauthenticated, like the rest of SCIM discovery.","tags":["SCIM"],"security":[],"responses":{"200":{"description":"The User and Group resource types.","content":{"application/json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"totalResults":{"type":"integer","description":"How many resources match, before pagination."},"startIndex":{"type":"integer"},"itemsPerPage":{"type":"integer"},"Resources":{"type":"array","items":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"id":{"type":"string"},"name":{"type":"string"},"endpoint":{"type":"string"},"schema":{"type":"string","description":"The URN of the schema this resource type is defined by."},"meta":{"type":"object","properties":{"resourceType":{"type":"string"},"location":{"type":"string"}}}}}}}}}}}}}},"/api/scim/v2/Schemas":{"get":{"operationId":"scimListSchemas","summary":"List the SCIM resource schemas","description":"The attribute definitions for the User and Group resources (RFC 7643 section 7), which an identity provider reads to build its attribute mapping. A LangWatch group is an access group: its membership drives role bindings, and it is not a team. Unauthenticated, like the rest of SCIM discovery.","tags":["SCIM"],"security":[],"responses":{"200":{"description":"The User and Group schema definitions.","content":{"application/json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"totalResults":{"type":"integer","description":"How many resources match, before pagination."},"startIndex":{"type":"integer"},"itemsPerPage":{"type":"integer"},"Resources":{"type":"array","items":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"id":{"type":"string","description":"The schema URN."},"name":{"type":"string"},"description":{"type":"string"},"attributes":{"type":"array","description":"The attribute definitions, in the shape RFC 7643 section 7 gives them.","items":{"type":"object"}},"meta":{"type":"object","properties":{"resourceType":{"type":"string"},"location":{"type":"string"}}}}}}}}}}}}}},"/api/scim/v2/Users":{"get":{"operationId":"scimListUsers","summary":"List provisioned users","description":"The members of the organization the token belongs to, as SCIM users. One filter expression is understood, `userName eq \"someone@example.com\"`, matched against the member's email without regard to case.","tags":["SCIM"],"security":[{"scim_bearer":[]}],"parameters":[{"name":"filter","in":"query","required":false,"schema":{"type":"string"},"description":"A SCIM filter. Only `userName eq \"...\"` is applied; anything else is ignored and the full page is returned."},{"name":"startIndex","in":"query","required":false,"schema":{"type":"integer","default":1},"description":"1-based index of the first resource to return. Anything that does not parse as a positive integer is read as 1."},{"name":"count","in":"query","required":false,"schema":{"type":"integer","default":100,"maximum":100},"description":"How many resources to return, capped at 100 (the `filter.maxResults` ServiceProviderConfig publishes). Anything that does not parse as a positive integer is read as 100, and anything above 100 is served as 100."}],"responses":{"200":{"description":"A page of provisioned users.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"totalResults":{"type":"integer","description":"How many resources match, before pagination."},"startIndex":{"type":"integer"},"itemsPerPage":{"type":"integer"},"Resources":{"type":"array","items":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"id":{"type":"string","description":"The LangWatch user id. Use it as the resource id in later calls, and as a member value on a group."},"userName":{"type":"string","format":"email","description":"The member's email address, which is their login."},"name":{"type":"object","properties":{"givenName":{"type":"string"},"familyName":{"type":"string"}}},"emails":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string","format":"email"},"primary":{"type":"boolean"},"type":{"type":"string"}}}},"active":{"type":"boolean","description":"False once the account is deactivated."},"meta":{"type":"object","properties":{"resourceType":{"type":"string"},"created":{"type":"string","format":"date-time"},"lastModified":{"type":"string","format":"date-time"}}}}}}}}}}},"401":{"description":"The Authorization header is missing, is not a bearer token, or names a token this deployment does not know.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"status":{"type":"string","description":"The HTTP status, as a string."},"detail":{"type":"string"}}}}}},"403":{"description":"The token is valid but the organization's plan no longer includes SCIM provisioning. Entitlement is checked on every call, so a directory connection stops the moment the Enterprise plan lapses.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"status":{"type":"string","description":"The HTTP status, as a string."},"detail":{"type":"string"}}}}}}}},"post":{"operationId":"scimCreateUser","summary":"Provision a user","description":"Adds a member to the organization, creating the LangWatch account when the email is new. Someone who already has an account is added and reactivated rather than refused, which is what lets a directory sync be re-run without special-casing the people it already knows. New members join with the MEMBER role at organization scope. `costCenter` on the enterprise user extension assigns their department, creating that department on first use.","tags":["SCIM"],"security":[{"scim_bearer":[]}],"responses":{"201":{"description":"The provisioned user.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"id":{"type":"string","description":"The LangWatch user id. Use it as the resource id in later calls, and as a member value on a group."},"userName":{"type":"string","format":"email","description":"The member's email address, which is their login."},"name":{"type":"object","properties":{"givenName":{"type":"string"},"familyName":{"type":"string"}}},"emails":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string","format":"email"},"primary":{"type":"boolean"},"type":{"type":"string"}}}},"active":{"type":"boolean","description":"False once the account is deactivated."},"meta":{"type":"object","properties":{"resourceType":{"type":"string"},"created":{"type":"string","format":"date-time"},"lastModified":{"type":"string","format":"date-time"}}}}}}}},"400":{"description":"The request body is not JSON, or does not match the SCIM schema for this operation.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"status":{"type":"string","description":"The HTTP status, as a string."},"detail":{"type":"string"}}}}}},"401":{"description":"The Authorization header is missing, is not a bearer token, or names a token this deployment does not know.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"status":{"type":"string","description":"The HTTP status, as a string."},"detail":{"type":"string"}}}}}},"403":{"description":"The token is valid but the organization's plan no longer includes SCIM provisioning. Entitlement is checked on every call, so a directory connection stops the moment the Enterprise plan lapses.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"status":{"type":"string","description":"The HTTP status, as a string."},"detail":{"type":"string"}}}}}},"409":{"description":"A member with this userName already exists in the organization.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"status":{"type":"string","description":"The HTTP status, as a string."},"detail":{"type":"string"}}}}}}}}},"/api/scim/v2/Users/{id}":{"get":{"operationId":"scimGetUser","summary":"Get a provisioned user","description":"Reads one member of the organization the token belongs to. An id that is not a member answers 404, whether or not it names a LangWatch account elsewhere.","tags":["SCIM"],"security":[{"scim_bearer":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The LangWatch user id."}],"responses":{"200":{"description":"The user.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"id":{"type":"string","description":"The LangWatch user id. Use it as the resource id in later calls, and as a member value on a group."},"userName":{"type":"string","format":"email","description":"The member's email address, which is their login."},"name":{"type":"object","properties":{"givenName":{"type":"string"},"familyName":{"type":"string"}}},"emails":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string","format":"email"},"primary":{"type":"boolean"},"type":{"type":"string"}}}},"active":{"type":"boolean","description":"False once the account is deactivated."},"meta":{"type":"object","properties":{"resourceType":{"type":"string"},"created":{"type":"string","format":"date-time"},"lastModified":{"type":"string","format":"date-time"}}}}}}}},"401":{"description":"The Authorization header is missing, is not a bearer token, or names a token this deployment does not know.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"status":{"type":"string","description":"The HTTP status, as a string."},"detail":{"type":"string"}}}}}},"403":{"description":"The token is valid but the organization's plan no longer includes SCIM provisioning. Entitlement is checked on every call, so a directory connection stops the moment the Enterprise plan lapses.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"status":{"type":"string","description":"The HTTP status, as a string."},"detail":{"type":"string"}}}}}},"404":{"description":"No such member in this organization.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"status":{"type":"string","description":"The HTTP status, as a string."},"detail":{"type":"string"}}}}}}}},"put":{"operationId":"scimReplaceUser","summary":"Replace a provisioned user","description":"Replaces the member's attributes with the body. It is a whole-resource write, so an attribute the identity provider leaves out is reset rather than kept: omitting `active` reactivates the member. Send PATCH instead to change one attribute.","tags":["SCIM"],"security":[{"scim_bearer":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The LangWatch user id."}],"responses":{"200":{"description":"The updated user.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"id":{"type":"string","description":"The LangWatch user id. Use it as the resource id in later calls, and as a member value on a group."},"userName":{"type":"string","format":"email","description":"The member's email address, which is their login."},"name":{"type":"object","properties":{"givenName":{"type":"string"},"familyName":{"type":"string"}}},"emails":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string","format":"email"},"primary":{"type":"boolean"},"type":{"type":"string"}}}},"active":{"type":"boolean","description":"False once the account is deactivated."},"meta":{"type":"object","properties":{"resourceType":{"type":"string"},"created":{"type":"string","format":"date-time"},"lastModified":{"type":"string","format":"date-time"}}}}}}}},"400":{"description":"The request body is not JSON, or does not match the SCIM schema for this operation.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"status":{"type":"string","description":"The HTTP status, as a string."},"detail":{"type":"string"}}}}}},"401":{"description":"The Authorization header is missing, is not a bearer token, or names a token this deployment does not know.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"status":{"type":"string","description":"The HTTP status, as a string."},"detail":{"type":"string"}}}}}},"403":{"description":"The token is valid but the organization's plan no longer includes SCIM provisioning. Entitlement is checked on every call, so a directory connection stops the moment the Enterprise plan lapses.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"status":{"type":"string","description":"The HTTP status, as a string."},"detail":{"type":"string"}}}}}},"404":{"description":"No such member in this organization.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"status":{"type":"string","description":"The HTTP status, as a string."},"detail":{"type":"string"}}}}}}}},"patch":{"operationId":"scimPatchUser","summary":"Update a provisioned user","description":"Applies RFC 7644 section 3.5.2 patch operations. What is implemented: `replace` of `active` (deactivating or reactivating the account), of `userName`, and of `name.givenName` / `name.familyName`, written either as an operation path or as keys inside a value object; and `add`, `replace` or `remove` of the enterprise `costCenter`, which reassigns the member's department. `replace`, `add` and `remove` are the only operation names understood, read without regard to case, so the capitalized `Replace` that Entra ID writes is accepted; any other name, or a missing or non-string one, is rejected with a 400. An understood operation aimed at anything not listed above is accepted and changes nothing.","tags":["SCIM"],"security":[{"scim_bearer":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The LangWatch user id."}],"responses":{"200":{"description":"The updated user.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"id":{"type":"string","description":"The LangWatch user id. Use it as the resource id in later calls, and as a member value on a group."},"userName":{"type":"string","format":"email","description":"The member's email address, which is their login."},"name":{"type":"object","properties":{"givenName":{"type":"string"},"familyName":{"type":"string"}}},"emails":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string","format":"email"},"primary":{"type":"boolean"},"type":{"type":"string"}}}},"active":{"type":"boolean","description":"False once the account is deactivated."},"meta":{"type":"object","properties":{"resourceType":{"type":"string"},"created":{"type":"string","format":"date-time"},"lastModified":{"type":"string","format":"date-time"}}}}}}}},"400":{"description":"The request body is not JSON, or does not match the SCIM schema for this operation.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"status":{"type":"string","description":"The HTTP status, as a string."},"detail":{"type":"string"}}}}}},"401":{"description":"The Authorization header is missing, is not a bearer token, or names a token this deployment does not know.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"status":{"type":"string","description":"The HTTP status, as a string."},"detail":{"type":"string"}}}}}},"403":{"description":"The token is valid but the organization's plan no longer includes SCIM provisioning. Entitlement is checked on every call, so a directory connection stops the moment the Enterprise plan lapses.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"status":{"type":"string","description":"The HTTP status, as a string."},"detail":{"type":"string"}}}}}},"404":{"description":"No such member in this organization.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"status":{"type":"string","description":"The HTTP status, as a string."},"detail":{"type":"string"}}}}}}}},"delete":{"operationId":"scimDeleteUser","summary":"Deprovision a user","description":"Removes the member from the organization, drops the role bindings they held there, and deactivates their account. The LangWatch user record itself is kept, so past traces, evaluations and audit entries stay attributable.","tags":["SCIM"],"security":[{"scim_bearer":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The LangWatch user id."}],"responses":{"204":{"description":"Deprovisioned. No body."},"401":{"description":"The Authorization header is missing, is not a bearer token, or names a token this deployment does not know.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"status":{"type":"string","description":"The HTTP status, as a string."},"detail":{"type":"string"}}}}}},"403":{"description":"The token is valid but the organization's plan no longer includes SCIM provisioning. Entitlement is checked on every call, so a directory connection stops the moment the Enterprise plan lapses.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"status":{"type":"string","description":"The HTTP status, as a string."},"detail":{"type":"string"}}}}}},"404":{"description":"No such member in this organization.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"status":{"type":"string","description":"The HTTP status, as a string."},"detail":{"type":"string"}}}}}}}}},"/api/scim/v2/Groups":{"get":{"operationId":"scimListGroups","summary":"List provisioned groups","description":"The organization's SCIM-provisioned access groups. Groups created in LangWatch itself are not listed: the directory sees what it provisioned, and nothing else. One filter expression is understood, `displayName eq \"Engineering\"`, matched without regard to case.","tags":["SCIM"],"security":[{"scim_bearer":[]}],"parameters":[{"name":"filter","in":"query","required":false,"schema":{"type":"string"},"description":"A SCIM filter. Only `displayName eq \"...\"` is applied; anything else is ignored and the full page is returned."},{"name":"startIndex","in":"query","required":false,"schema":{"type":"integer","default":1},"description":"1-based index of the first resource to return. Anything that does not parse as a positive integer is read as 1."},{"name":"count","in":"query","required":false,"schema":{"type":"integer","default":100,"maximum":100},"description":"How many resources to return, capped at 100 (the `filter.maxResults` ServiceProviderConfig publishes). Anything that does not parse as a positive integer is read as 100, and anything above 100 is served as 100."},{"name":"excludedAttributes","in":"query","required":false,"schema":{"type":"string"},"description":"Comma-separated attribute names to leave out of the response. Only `members` is honoured, and it is what lets a directory page through groups without pulling every membership."}],"responses":{"200":{"description":"A page of provisioned groups.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"totalResults":{"type":"integer","description":"How many resources match, before pagination."},"startIndex":{"type":"integer"},"itemsPerPage":{"type":"integer"},"Resources":{"type":"array","items":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"id":{"type":"string","description":"The LangWatch group id."},"displayName":{"type":"string"},"members":{"type":"array","description":"Omitted when the request excluded the members attribute. Each value is a LangWatch user id.","items":{"type":"object","properties":{"value":{"type":"string"},"display":{"type":"string"}}}},"meta":{"type":"object","properties":{"resourceType":{"type":"string"},"created":{"type":"string","format":"date-time"},"lastModified":{"type":"string","format":"date-time"}}}}}}}}}}},"401":{"description":"The Authorization header is missing, is not a bearer token, or names a token this deployment does not know.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"status":{"type":"string","description":"The HTTP status, as a string."},"detail":{"type":"string"}}}}}},"403":{"description":"The token is valid but the organization's plan no longer includes SCIM provisioning. Entitlement is checked on every call, so a directory connection stops the moment the Enterprise plan lapses.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"status":{"type":"string","description":"The HTTP status, as a string."},"detail":{"type":"string"}}}}}}}},"post":{"operationId":"scimCreateGroup","summary":"Provision a group","description":"Creates an access group. Members are given as LangWatch user ids, the same ids the Users endpoints return; an id that is not a member of the organization is skipped rather than failing the call, so a group can be provisioned before everyone in it is. Granting the group access is a separate step: a group carries no permissions until a role binding is created for it.","tags":["SCIM"],"security":[{"scim_bearer":[]}],"responses":{"201":{"description":"The provisioned group.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"id":{"type":"string","description":"The LangWatch group id."},"displayName":{"type":"string"},"members":{"type":"array","description":"Omitted when the request excluded the members attribute. Each value is a LangWatch user id.","items":{"type":"object","properties":{"value":{"type":"string"},"display":{"type":"string"}}}},"meta":{"type":"object","properties":{"resourceType":{"type":"string"},"created":{"type":"string","format":"date-time"},"lastModified":{"type":"string","format":"date-time"}}}}}}}},"400":{"description":"The request body is not JSON, or does not match the SCIM schema for this operation.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"status":{"type":"string","description":"The HTTP status, as a string."},"detail":{"type":"string"}}}}}},"401":{"description":"The Authorization header is missing, is not a bearer token, or names a token this deployment does not know.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"status":{"type":"string","description":"The HTTP status, as a string."},"detail":{"type":"string"}}}}}},"403":{"description":"The token is valid but the organization's plan no longer includes SCIM provisioning. Entitlement is checked on every call, so a directory connection stops the moment the Enterprise plan lapses.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"status":{"type":"string","description":"The HTTP status, as a string."},"detail":{"type":"string"}}}}}},"409":{"description":"A provisioned group with this displayName already exists in the organization.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"status":{"type":"string","description":"The HTTP status, as a string."},"detail":{"type":"string"}}}}}}}}},"/api/scim/v2/Groups/{id}":{"get":{"operationId":"scimGetGroup","summary":"Get a provisioned group","description":"Reads one provisioned group and its members. A group that exists but was created in LangWatch rather than provisioned is not readable here.","tags":["SCIM"],"security":[{"scim_bearer":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The LangWatch group id."},{"name":"excludedAttributes","in":"query","required":false,"schema":{"type":"string"},"description":"Comma-separated attribute names to leave out of the response. Only `members` is honoured, and it is what lets a directory page through groups without pulling every membership."}],"responses":{"200":{"description":"The group.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"id":{"type":"string","description":"The LangWatch group id."},"displayName":{"type":"string"},"members":{"type":"array","description":"Omitted when the request excluded the members attribute. Each value is a LangWatch user id.","items":{"type":"object","properties":{"value":{"type":"string"},"display":{"type":"string"}}}},"meta":{"type":"object","properties":{"resourceType":{"type":"string"},"created":{"type":"string","format":"date-time"},"lastModified":{"type":"string","format":"date-time"}}}}}}}},"401":{"description":"The Authorization header is missing, is not a bearer token, or names a token this deployment does not know.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"status":{"type":"string","description":"The HTTP status, as a string."},"detail":{"type":"string"}}}}}},"403":{"description":"The token is valid but the organization's plan no longer includes SCIM provisioning. Entitlement is checked on every call, so a directory connection stops the moment the Enterprise plan lapses.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"status":{"type":"string","description":"The HTTP status, as a string."},"detail":{"type":"string"}}}}}},"404":{"description":"No such group in this organization.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"status":{"type":"string","description":"The HTTP status, as a string."},"detail":{"type":"string"}}}}}}}},"put":{"operationId":"scimReplaceGroup","summary":"Replace a provisioned group","description":"Replaces the group's display name and its membership with the body. Membership is a whole-resource write: a member absent from `members` is removed from the group, and omitting `members` empties it. Role bindings granted to the group are untouched.","tags":["SCIM"],"security":[{"scim_bearer":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The LangWatch group id."}],"responses":{"200":{"description":"The updated group.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"id":{"type":"string","description":"The LangWatch group id."},"displayName":{"type":"string"},"members":{"type":"array","description":"Omitted when the request excluded the members attribute. Each value is a LangWatch user id.","items":{"type":"object","properties":{"value":{"type":"string"},"display":{"type":"string"}}}},"meta":{"type":"object","properties":{"resourceType":{"type":"string"},"created":{"type":"string","format":"date-time"},"lastModified":{"type":"string","format":"date-time"}}}}}}}},"400":{"description":"The request body is not JSON, or does not match the SCIM schema for this operation.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"status":{"type":"string","description":"The HTTP status, as a string."},"detail":{"type":"string"}}}}}},"401":{"description":"The Authorization header is missing, is not a bearer token, or names a token this deployment does not know.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"status":{"type":"string","description":"The HTTP status, as a string."},"detail":{"type":"string"}}}}}},"403":{"description":"The token is valid but the organization's plan no longer includes SCIM provisioning. Entitlement is checked on every call, so a directory connection stops the moment the Enterprise plan lapses.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"status":{"type":"string","description":"The HTTP status, as a string."},"detail":{"type":"string"}}}}}},"404":{"description":"No such group in this organization.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"status":{"type":"string","description":"The HTTP status, as a string."},"detail":{"type":"string"}}}}}}}},"patch":{"operationId":"scimPatchGroup","summary":"Update a provisioned group","description":"Applies RFC 7644 section 3.5.2 patch operations. What is implemented: `add` of members, `remove` of members (named by a value filter on the path, as Entra ID writes it, or in the operation value), `replace` of `displayName`, and `replace` of the whole member list. `replace`, `add` and `remove` are the only operation names understood, read without regard to case, so the capitalized `Add` / `Remove` that Entra ID writes are accepted; any other name, or a missing or non-string one, is rejected with a 400. An `add` or a `remove` aimed at anything other than members is accepted and changes nothing. A `replace` that is not a `displayName` rename is treated as a replacement of the whole member list, so one that carries no members empties the group.","tags":["SCIM"],"security":[{"scim_bearer":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The LangWatch group id."}],"responses":{"200":{"description":"The updated group.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"id":{"type":"string","description":"The LangWatch group id."},"displayName":{"type":"string"},"members":{"type":"array","description":"Omitted when the request excluded the members attribute. Each value is a LangWatch user id.","items":{"type":"object","properties":{"value":{"type":"string"},"display":{"type":"string"}}}},"meta":{"type":"object","properties":{"resourceType":{"type":"string"},"created":{"type":"string","format":"date-time"},"lastModified":{"type":"string","format":"date-time"}}}}}}}},"400":{"description":"The request body is not JSON, or does not match the SCIM schema for this operation.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"status":{"type":"string","description":"The HTTP status, as a string."},"detail":{"type":"string"}}}}}},"401":{"description":"The Authorization header is missing, is not a bearer token, or names a token this deployment does not know.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"status":{"type":"string","description":"The HTTP status, as a string."},"detail":{"type":"string"}}}}}},"403":{"description":"The token is valid but the organization's plan no longer includes SCIM provisioning. Entitlement is checked on every call, so a directory connection stops the moment the Enterprise plan lapses.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"status":{"type":"string","description":"The HTTP status, as a string."},"detail":{"type":"string"}}}}}},"404":{"description":"No such group in this organization.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"status":{"type":"string","description":"The HTTP status, as a string."},"detail":{"type":"string"}}}}}}}},"delete":{"operationId":"scimDeleteGroup","summary":"Deprovision a group","description":"Deletes the group along with its memberships and every role binding granted through it, so the access it carried is revoked with it. The members themselves keep their organization membership and any access they hold directly.","tags":["SCIM"],"security":[{"scim_bearer":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The LangWatch group id."}],"responses":{"204":{"description":"Deprovisioned. No body."},"401":{"description":"The Authorization header is missing, is not a bearer token, or names a token this deployment does not know.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"status":{"type":"string","description":"The HTTP status, as a string."},"detail":{"type":"string"}}}}}},"403":{"description":"The token is valid but the organization's plan no longer includes SCIM provisioning. Entitlement is checked on every call, so a directory connection stops the moment the Enterprise plan lapses.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"status":{"type":"string","description":"The HTTP status, as a string."},"detail":{"type":"string"}}}}}},"404":{"description":"No such group in this organization.","content":{"application/scim+json":{"schema":{"type":"object","properties":{"schemas":{"type":"array","items":{"type":"string"},"description":"The SCIM schema URNs this resource conforms to."},"status":{"type":"string","description":"The HTTP status, as a string."},"detail":{"type":"string"}}}}}}}}},"/api/scenario-events":{"post":{"operationId":"postApiScenarioEvents","description":"Create a new scenario event","responses":{"201":{"description":"Event created successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"url":{"type":["string","null"]}},"required":["success"]}}}},"400":{"description":"Invalid event data","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"SCENARIO_RUN_STARTED"},"timestamp":{"type":"number"},"rawEvent":{},"batchRunId":{"type":"string"},"scenarioId":{"type":"string"},"scenarioRunId":{"type":"string"},"scenarioSetId":{"type":"string","default":"default"},"metadata":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"note":{"type":"string"},"agents":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"role":{"type":"string","enum":["agent","user","judge"]}},"required":["name","role"]}},"langwatch":{"type":"object","properties":{"targetReferenceId":{"type":"string"},"targetType":{"type":"string","enum":["prompt","http","code","workflow","connected","voice"]},"targetKey":{"type":"string"},"targetParameters":{"type":"object","additionalProperties":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]}},"simulationSuiteId":{"type":"string"},"scenarioVersion":{"type":"integer"},"simulatorModel":{"type":"string"},"judgeModel":{"type":"string"},"resolvedSimulatorModel":{"type":"string"},"resolvedJudgeModel":{"type":"string"},"actorId":{"type":"string"},"actorLabel":{"type":"string","enum":["user","api","cli"]},"agentInstance":{"type":"object","properties":{"hostname":{"type":"string"},"label":{"type":["string","null"]}},"required":["hostname","label"]},"callerKind":{"type":"string","enum":["simulated","human"]},"caller":{"type":"object","properties":{"voice":{"type":"string"},"interruptProbability":{"type":"number"},"effects":{"type":"string"}},"required":["voice","interruptProbability","effects"]},"isCutAtLimit":{"type":"boolean"}},"required":["targetReferenceId","targetType"]}},"additionalProperties":true}},"required":["type","timestamp","batchRunId","scenarioId","scenarioRunId","metadata"]},{"type":"object","properties":{"type":{"type":"string","const":"SCENARIO_RUN_FINISHED"},"timestamp":{"type":"number"},"rawEvent":{},"batchRunId":{"type":"string"},"scenarioId":{"type":"string"},"scenarioRunId":{"type":"string"},"scenarioSetId":{"type":"string","default":"default"},"status":{"type":"string","enum":["SUCCESS","ERROR","CANCELLED","IN_PROGRESS","PENDING","FAILED","STALLED","QUEUED","RUNNING","PENDING_EVALUATION"]},"results":{"type":["object","null"],"properties":{"verdict":{"type":"string","enum":["success","failure","inconclusive"]},"reasoning":{"type":"string"},"metCriteria":{"type":"array","items":{"type":"string"}},"unmetCriteria":{"type":"array","items":{"type":"string"}},"inconclusiveCriteria":{"type":"array","items":{"type":"string"}},"error":{"type":"string"},"evaluations":{"type":"array","items":{"type":"object","properties":{"evaluatorId":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","enum":["passed","failed","scored","skipped","error"]},"required":{"type":"boolean"},"passed":{"type":"boolean"},"score":{"type":"number"},"label":{"type":"string"},"details":{"type":"string"},"cost":{"type":"object","properties":{"currency":{"type":"string"},"amount":{"type":"number"}},"required":["currency","amount"]},"inputs":{"type":"object","additionalProperties":{"type":"string"}}},"required":["evaluatorId","name","status","required"]}}},"required":["verdict","metCriteria","unmetCriteria"]}},"required":["type","timestamp","batchRunId","scenarioId","scenarioRunId","status"]},{"type":"object","properties":{"type":{"type":"string","const":"SCENARIO_MESSAGE_SNAPSHOT"},"timestamp":{"type":"number"},"rawEvent":{},"messages":{"type":"array","items":{"allOf":[{"anyOf":[{"oneOf":[{"type":"object","properties":{"id":{"type":"string"},"role":{"type":"string","const":"developer"},"content":{"type":"string"},"name":{"type":"string"},"encryptedValue":{"type":"string"}},"required":["id","role","content"]},{"type":"object","properties":{"id":{"type":"string"},"role":{"type":"string","const":"system"},"content":{"type":"string"},"name":{"type":"string"},"encryptedValue":{"type":"string"}},"required":["id","role","content"]},{"type":"object","properties":{"id":{"type":"string"},"role":{"type":"string","const":"assistant"},"content":{"type":"string"},"name":{"type":"string"},"encryptedValue":{"type":"string"},"toolCalls":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string","const":"function"},"function":{"type":"object","properties":{"name":{"type":"string"},"arguments":{"type":"string"}},"required":["name","arguments"]},"encryptedValue":{"type":"string"}},"required":["id","type","function"]}}},"required":["id","role"]},{"type":"object","properties":{"id":{"type":"string"},"role":{"type":"string","const":"user"},"content":{"anyOf":[{"type":"string"},{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"text"},"text":{"type":"string"}},"required":["type","text"]},{"type":"object","properties":{"type":{"type":"string","const":"image"},"source":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"data"},"value":{"type":"string"},"mimeType":{"type":"string"}},"required":["type","value","mimeType"]},{"type":"object","properties":{"type":{"type":"string","const":"url"},"value":{"type":"string"},"mimeType":{"type":"string"}},"required":["type","value"]}]},"metadata":{}},"required":["type","source"]},{"type":"object","properties":{"type":{"type":"string","const":"audio"},"source":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"data"},"value":{"type":"string"},"mimeType":{"type":"string"}},"required":["type","value","mimeType"]},{"type":"object","properties":{"type":{"type":"string","const":"url"},"value":{"type":"string"},"mimeType":{"type":"string"}},"required":["type","value"]}]},"metadata":{}},"required":["type","source"]},{"type":"object","properties":{"type":{"type":"string","const":"video"},"source":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"data"},"value":{"type":"string"},"mimeType":{"type":"string"}},"required":["type","value","mimeType"]},{"type":"object","properties":{"type":{"type":"string","const":"url"},"value":{"type":"string"},"mimeType":{"type":"string"}},"required":["type","value"]}]},"metadata":{}},"required":["type","source"]},{"type":"object","properties":{"type":{"type":"string","const":"document"},"source":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"data"},"value":{"type":"string"},"mimeType":{"type":"string"}},"required":["type","value","mimeType"]},{"type":"object","properties":{"type":{"type":"string","const":"url"},"value":{"type":"string"},"mimeType":{"type":"string"}},"required":["type","value"]}]},"metadata":{}},"required":["type","source"]},{"type":"object","properties":{"type":{"type":"string","const":"binary"},"mimeType":{"type":"string"},"id":{"type":"string"},"url":{"type":"string"},"data":{"type":"string"},"filename":{"type":"string"}},"required":["type","mimeType"]}]}}]},"name":{"type":"string"},"encryptedValue":{"type":"string"}},"required":["id","role","content"]},{"type":"object","properties":{"id":{"type":"string"},"content":{"type":"string"},"role":{"type":"string","const":"tool"},"toolCallId":{"type":"string"},"error":{"type":"string"},"encryptedValue":{"type":"string"}},"required":["id","content","role","toolCallId"]},{"type":"object","properties":{"id":{"type":"string"},"role":{"type":"string","const":"activity"},"activityType":{"type":"string"},"content":{"type":"object","additionalProperties":{}}},"required":["id","role","activityType","content"]},{"type":"object","properties":{"id":{"type":"string"},"role":{"type":"string","const":"reasoning"},"content":{"type":"string"},"encryptedValue":{"type":"string"}},"required":["id","role","content"]}]},{"type":"object","properties":{"role":{"type":"string"},"content":{"type":"array","items":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"text"},"text":{"type":"string"},"citations":{"type":["array","null"],"items":{}}},"required":["type","text"]},{"type":"object","properties":{"type":{"type":"string","const":"tool_use"},"id":{"type":"string"},"name":{"type":"string"},"input":{}},"required":["type","id","name"]},{"type":"object","properties":{"type":{"type":"string","const":"tool_result"},"tool_use_id":{"type":"string"},"content":{"anyOf":[{"type":"string"},{"type":"array","items":{}}]},"is_error":{"type":"boolean"}},"required":["type","tool_use_id"]},{"type":"object","properties":{"type":{"type":"string","const":"thinking"},"thinking":{"type":"string"},"signature":{"type":"string"}},"required":["type","thinking"]},{"type":"object","properties":{"type":{"type":"string","const":"redacted_thinking"},"data":{"type":"string"}},"required":["type","data"]}]}}},"required":["content"]},{"type":"object","properties":{"role":{"anyOf":[{"type":"string","const":"system"},{"type":"string","const":"developer"},{"type":"string","const":"user"},{"type":"string","const":"assistant"},{"type":"string","const":"function"},{"type":"string","const":"tool"},{"type":"string","const":"unknown"}]},"content":{"anyOf":[{"type":"string"},{"type":"array","items":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"text"},"text":{"type":"string"},"content":{"type":"string"}},"required":["type"]},{"type":"object","properties":{"text":{"type":"string"}},"required":["text"]},{"type":"object","properties":{"type":{"type":"string","const":"image_url"},"image_url":{"type":"object","properties":{"url":{"type":"string"},"detail":{"anyOf":[{"type":"string","const":"auto"},{"type":"string","const":"low"},{"type":"string","const":"high"}]}},"required":["url"]}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"tool_call"},"toolName":{"type":"string"},"toolCallId":{"type":"string"},"args":{"type":"string"}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"tool_result"},"toolName":{"type":"string"},"toolCallId":{"type":"string"},"result":{}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"binary"},"mimeType":{"type":"string"},"data":{"type":"string"},"url":{"type":"string"},"id":{"type":"string"},"filename":{"type":"string"}},"required":["type","mimeType"]},{"type":"object","properties":{"type":{"type":"string","const":"input_audio"},"input_audio":{"type":"object","properties":{"data":{"type":"string"},"format":{"type":"string"},"url":{"type":"string"},"mimeType":{"type":"string"},"id":{"type":"string"}}}},"required":["type","input_audio"]},{"type":"object","properties":{"type":{"type":"string","const":"audio"},"source":{"type":"object","properties":{"type":{"anyOf":[{"type":"string","const":"url"},{"type":"string","const":"data"}]},"value":{"type":"string"},"mimeType":{"type":"string"}},"required":["type","value"]}},"required":["type","source"]},{"type":"object","properties":{"type":{"type":"string","const":"image"},"image":{"type":"string"},"mediaType":{"type":"string"}},"required":["type","image"]},{"type":"object","properties":{"type":{"type":"string","const":"file"},"mediaType":{"type":"string"},"data":{"type":"string"},"url":{"type":"string"},"filename":{"type":"string"}},"required":["type","mediaType"]},{"type":"object","properties":{"type":{"type":"string","const":"file"},"file":{"type":"object","properties":{"file_data":{"type":"string"},"file_id":{"type":"string"},"filename":{"type":"string"}}}},"required":["type","file"]}]}},{"type":"null"}]},"parts":{"type":"array","items":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"text"},"text":{"type":"string"},"content":{"type":"string"}},"required":["type"]},{"type":"object","properties":{"text":{"type":"string"}},"required":["text"]},{"type":"object","properties":{"type":{"type":"string","const":"image_url"},"image_url":{"type":"object","properties":{"url":{"type":"string"},"detail":{"anyOf":[{"type":"string","const":"auto"},{"type":"string","const":"low"},{"type":"string","const":"high"}]}},"required":["url"]}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"tool_call"},"toolName":{"type":"string"},"toolCallId":{"type":"string"},"args":{"type":"string"}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"tool_result"},"toolName":{"type":"string"},"toolCallId":{"type":"string"},"result":{}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"binary"},"mimeType":{"type":"string"},"data":{"type":"string"},"url":{"type":"string"},"id":{"type":"string"},"filename":{"type":"string"}},"required":["type","mimeType"]},{"type":"object","properties":{"type":{"type":"string","const":"input_audio"},"input_audio":{"type":"object","properties":{"data":{"type":"string"},"format":{"type":"string"},"url":{"type":"string"},"mimeType":{"type":"string"},"id":{"type":"string"}}}},"required":["type","input_audio"]},{"type":"object","properties":{"type":{"type":"string","const":"audio"},"source":{"type":"object","properties":{"type":{"anyOf":[{"type":"string","const":"url"},{"type":"string","const":"data"}]},"value":{"type":"string"},"mimeType":{"type":"string"}},"required":["type","value"]}},"required":["type","source"]},{"type":"object","properties":{"type":{"type":"string","const":"image"},"image":{"type":"string"},"mediaType":{"type":"string"}},"required":["type","image"]},{"type":"object","properties":{"type":{"type":"string","const":"file"},"mediaType":{"type":"string"},"data":{"type":"string"},"url":{"type":"string"},"filename":{"type":"string"}},"required":["type","mediaType"]},{"type":"object","properties":{"type":{"type":"string","const":"file"},"file":{"type":"object","properties":{"file_data":{"type":"string"},"file_id":{"type":"string"},"filename":{"type":"string"}}}},"required":["type","file"]}]}},"function_call":{"type":["object","null"],"properties":{"name":{"type":"string"},"arguments":{"type":"string"}}},"tool_calls":{"type":["array","null"],"items":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string"},"function":{"type":"object","properties":{"name":{"type":"string"},"arguments":{"type":"string"}}}},"required":["id","type","function"]}},"tool_call_id":{"type":["string","null"]},"name":{"type":["string","null"]},"reasoning_content":{"type":["string","null"]}}},{"type":"object","properties":{"role":{"type":"string"},"content":{"type":"array","items":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"text"},"text":{"type":"string"}},"required":["type","text"]},{"type":"object","properties":{"type":{"type":"string","const":"input_audio"},"input_audio":{"type":"object","properties":{"data":{"type":"string"},"format":{"type":"string"},"mimeType":{"type":"string"},"url":{"type":"string"},"id":{"type":"string"}}}},"required":["type","input_audio"]}]}}},"required":["content"]}]},{"type":"object","properties":{"id":{"type":"string"},"trace_id":{"type":"string"}}}]}},"batchRunId":{"type":"string"},"scenarioId":{"type":"string"},"scenarioRunId":{"type":"string"},"scenarioSetId":{"type":"string","default":"default"}},"required":["type","timestamp","messages","batchRunId","scenarioId","scenarioRunId"]},{"type":"object","properties":{"type":{"type":"string","const":"SCENARIO_TEXT_MESSAGE_START"},"timestamp":{"type":"number"},"rawEvent":{},"batchRunId":{"type":"string"},"scenarioId":{"type":"string"},"scenarioRunId":{"type":"string"},"scenarioSetId":{"type":"string","default":"default"},"messageId":{"type":"string"},"role":{"type":"string"},"messageIndex":{"type":"number"}},"required":["type","timestamp","batchRunId","scenarioId","scenarioRunId","messageId","role"]},{"type":"object","properties":{"type":{"type":"string","const":"SCENARIO_TEXT_MESSAGE_END"},"timestamp":{"type":"number"},"rawEvent":{},"batchRunId":{"type":"string"},"scenarioId":{"type":"string"},"scenarioRunId":{"type":"string"},"scenarioSetId":{"type":"string","default":"default"},"messageId":{"type":"string"},"role":{"type":"string"},"content":{"type":"string"},"message":{"type":"object","additionalProperties":{}},"traceId":{"type":"string"},"messageIndex":{"type":"number"}},"required":["type","timestamp","batchRunId","scenarioId","scenarioRunId","messageId","role"]},{"type":"object","properties":{"type":{"type":"string","const":"SCENARIO_TEXT_MESSAGE_CONTENT"},"timestamp":{"type":"number"},"rawEvent":{},"batchRunId":{"type":"string"},"scenarioId":{"type":"string"},"scenarioRunId":{"type":"string"},"scenarioSetId":{"type":"string","default":"default"},"messageId":{"type":"string"},"delta":{"type":"string"}},"required":["type","timestamp","batchRunId","scenarioId","scenarioRunId","messageId","delta"]},{"type":"object","properties":{"type":{"type":"string","const":"SCENARIO_TOOL_CALL_START"},"timestamp":{"type":"number"},"rawEvent":{},"batchRunId":{"type":"string"},"scenarioId":{"type":"string"},"scenarioRunId":{"type":"string"},"scenarioSetId":{"type":"string","default":"default"},"toolCallId":{"type":"string"},"toolCallName":{"type":"string"},"parentMessageId":{"type":"string"}},"required":["type","timestamp","batchRunId","scenarioId","scenarioRunId","toolCallId","toolCallName"]},{"type":"object","properties":{"type":{"type":"string","const":"SCENARIO_TOOL_CALL_ARGS"},"timestamp":{"type":"number"},"rawEvent":{},"batchRunId":{"type":"string"},"scenarioId":{"type":"string"},"scenarioRunId":{"type":"string"},"scenarioSetId":{"type":"string","default":"default"},"toolCallId":{"type":"string"},"delta":{"type":"string"}},"required":["type","timestamp","batchRunId","scenarioId","scenarioRunId","toolCallId","delta"]},{"type":"object","properties":{"type":{"type":"string","const":"SCENARIO_TOOL_CALL_END"},"timestamp":{"type":"number"},"rawEvent":{},"batchRunId":{"type":"string"},"scenarioId":{"type":"string"},"scenarioRunId":{"type":"string"},"scenarioSetId":{"type":"string","default":"default"},"toolCallId":{"type":"string"}},"required":["type","timestamp","batchRunId","scenarioId","scenarioRunId","toolCallId"]}]}}}},"security":[{"project_api_key":[]}]},"delete":{"operationId":"deleteApiScenarioEvents","description":"Archive simulation runs. Pass exactly one of `scenarioSetId` (archives every run in the set; `scenarioSetId=default` targets the implicit default set) or `scenarioRunId` (archives that one run).","responses":{"200":{"description":"Runs archived successfully","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"archived":{"type":"integer","minimum":0},"failed":{"type":"integer","minimum":0},"scenarioSetId":{"type":"string"},"hasMore":{"type":"boolean"}},"required":["archived","failed","scenarioSetId","hasMore"]},{"type":"object","properties":{"archived":{"type":"integer","minimum":0},"failed":{"type":"integer","minimum":0},"scenarioRunId":{"type":"string"}},"required":["archived","failed","scenarioRunId"]}]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Scenario run not found in this project","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Missing or invalid scope parameter","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"parameters":[{"in":"query","name":"scenarioSetId","schema":{"type":"string","minLength":1}},{"in":"query","name":"scenarioRunId","schema":{"type":"string","minLength":1}}],"security":[{"project_api_key":[]}]}},"/api/scenario-events/browser-tab":{"post":{"operationId":"postApiScenarioEventsBrowserTab","description":"Offer a batch run to an already-open simulations tab on the caller's machine. Returns whether a live tab took it.","responses":{"200":{"description":"Handoff evaluated","content":{"application/json":{"schema":{"type":"object","properties":{"delivered":{"type":"boolean"},"url":{"type":"string"}},"required":["delivered","url"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"tabKey":{"type":"string","minLength":1,"maxLength":200},"batchRunId":{"type":"string","minLength":1,"maxLength":200},"scenarioSetId":{"type":"string","minLength":1,"maxLength":200}},"required":["tabKey","batchRunId"]}}}},"security":[{"project_api_key":[]}]}},"/api/scenarios":{"get":{"operationId":"getApiScenarios","description":"Get all scenarios for a project","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"situation":{"type":"string"},"criteria":{"type":"array","items":{"type":"string"}},"labels":{"type":"array","items":{"type":"string"}},"parameters":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","pattern":"^[A-Za-z_][A-Za-z0-9_]*$","minLength":1,"maxLength":64},"description":{"type":"string","maxLength":500},"defaultValue":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"secret":{"type":"boolean"},"type":{"type":"string","enum":["string","number","boolean"]},"options":{"type":"array","items":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"maxItems":50},"required":{"type":"boolean"}},"required":["name"]}},"simulatorModel":{"type":["string","null"],"description":"The model that plays the user, or null for the project default. Absent on servers that predate model overrides on this family."},"judgeModel":{"type":["string","null"],"description":"The model that judges the run, or null for the project default. Absent on servers that predate model overrides on this family."},"maxTurns":{"type":["integer","null"],"description":"The most conversation turns a run of this scenario takes, or null for the default. Absent on servers that predate turn limits on this family."},"minTurns":{"type":["integer","null"],"description":"The fewest conversation turns before the judge may end a run, or null for the default. Absent on servers that predate turn limits on this family."},"testSuiteId":{"type":["string","null"],"description":"The test suite this scenario is filed in, or null when unfiled. Absent on servers that predate test suites."},"fields":{"type":"object","propertyNames":{"type":"string","maxLength":64},"additionalProperties":{"anyOf":[{"type":"string","maxLength":65536},{"type":"number"},{"type":"boolean"}]},"description":"The value this scenario carries for each field its test suite declares, keyed by field identifier. A field with no value has no key. Absent on servers that predate suite fields."},"platformUrl":{"type":"string","format":"uri"}},"required":["id","name","situation","criteria","labels","parameters","platformUrl"]}}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"security":[{"project_api_key":[]}]},"post":{"operationId":"postApiScenarios","description":"Create a new scenario","responses":{"201":{"description":"Scenario created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"situation":{"type":"string"},"criteria":{"type":"array","items":{"type":"string"}},"labels":{"type":"array","items":{"type":"string"}},"parameters":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","pattern":"^[A-Za-z_][A-Za-z0-9_]*$","minLength":1,"maxLength":64},"description":{"type":"string","maxLength":500},"defaultValue":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"secret":{"type":"boolean"},"type":{"type":"string","enum":["string","number","boolean"]},"options":{"type":"array","items":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"maxItems":50},"required":{"type":"boolean"}},"required":["name"]}},"simulatorModel":{"type":["string","null"],"description":"The model that plays the user, or null for the project default. Absent on servers that predate model overrides on this family."},"judgeModel":{"type":["string","null"],"description":"The model that judges the run, or null for the project default. Absent on servers that predate model overrides on this family."},"maxTurns":{"type":["integer","null"],"description":"The most conversation turns a run of this scenario takes, or null for the default. Absent on servers that predate turn limits on this family."},"minTurns":{"type":["integer","null"],"description":"The fewest conversation turns before the judge may end a run, or null for the default. Absent on servers that predate turn limits on this family."},"testSuiteId":{"type":["string","null"],"description":"The test suite this scenario is filed in, or null when unfiled. Absent on servers that predate test suites."},"fields":{"type":"object","propertyNames":{"type":"string","maxLength":64},"additionalProperties":{"anyOf":[{"type":"string","maxLength":65536},{"type":"number"},{"type":"boolean"}]},"description":"The value this scenario carries for each field its test suite declares, keyed by field identifier. A field with no value has no key. Absent on servers that predate suite fields."},"platformUrl":{"type":"string","format":"uri"}},"required":["id","name","situation","criteria","labels","parameters","platformUrl"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1},"situation":{"type":"string"},"criteria":{"type":"array","items":{"type":"string"},"default":[]},"labels":{"type":"array","items":{"type":"string"},"default":[]},"parameters":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","pattern":"^[A-Za-z_][A-Za-z0-9_]*$","minLength":1,"maxLength":64},"description":{"type":"string","maxLength":500},"defaultValue":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"secret":{"type":"boolean"},"type":{"type":"string","enum":["string","number","boolean"]},"options":{"type":"array","items":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"maxItems":50},"required":{"type":"boolean"}},"required":["name"]},"maxItems":20,"description":"The parameters this scenario declares by name, each with an optional description and default. A run supplies values for these names, readable from the scenario's own text as params.NAME. A parameter marked secret carries no default: its value is supplied per run, encrypted, delivered to the target as secrets.NAME, and never readable from the scenario's own text."},"simulatorModel":{"type":["string","null"],"pattern":"^[a-zA-Z0-9_-]+(?:\\/[^\\s/]+)+$","maxLength":200,"description":"Model for the simulated user, e.g. openai/gpt-5-mini. Null uses the project default."},"judgeModel":{"type":["string","null"],"pattern":"^[a-zA-Z0-9_-]+(?:\\/[^\\s/]+)+$","maxLength":200,"description":"Model for the judge, e.g. openai/gpt-5-mini. Null uses the project default."},"maxTurns":{"type":["integer","null"],"minimum":1,"maximum":100,"description":"Maximum conversation turns for a run of this scenario. Null uses the default."},"minTurns":{"type":["integer","null"],"minimum":0,"maximum":100,"description":"Minimum conversation turns before the judge may end the run. Null uses the default."},"testSuiteId":{"type":["string","null"],"description":"The test suite to file this scenario in. It must name a non-archived test suite of the same project. null files the scenario into the project's Default test suite."},"fields":{"type":"object","propertyNames":{"type":"string","maxLength":64},"additionalProperties":{"anyOf":[{"type":"string","maxLength":65536},{"type":"number"},{"type":"boolean"}]},"description":"The value for each field the test suite declares, keyed by field identifier: text, a number or a boolean, in the field's own type. A field the suite does not declare answers 422 scenario_field_unknown; a value of the wrong type answers 422 scenario_field_type_invalid. An empty value clears the field."}},"required":["name","situation"]}}}},"security":[{"project_api_key":[]}]}},"/api/scenarios/{id}":{"get":{"operationId":"getApiScenariosById","description":"Get a specific scenario by ID","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"situation":{"type":"string"},"criteria":{"type":"array","items":{"type":"string"}},"labels":{"type":"array","items":{"type":"string"}},"parameters":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","pattern":"^[A-Za-z_][A-Za-z0-9_]*$","minLength":1,"maxLength":64},"description":{"type":"string","maxLength":500},"defaultValue":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"secret":{"type":"boolean"},"type":{"type":"string","enum":["string","number","boolean"]},"options":{"type":"array","items":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"maxItems":50},"required":{"type":"boolean"}},"required":["name"]}},"simulatorModel":{"type":["string","null"],"description":"The model that plays the user, or null for the project default. Absent on servers that predate model overrides on this family."},"judgeModel":{"type":["string","null"],"description":"The model that judges the run, or null for the project default. Absent on servers that predate model overrides on this family."},"maxTurns":{"type":["integer","null"],"description":"The most conversation turns a run of this scenario takes, or null for the default. Absent on servers that predate turn limits on this family."},"minTurns":{"type":["integer","null"],"description":"The fewest conversation turns before the judge may end a run, or null for the default. Absent on servers that predate turn limits on this family."},"testSuiteId":{"type":["string","null"],"description":"The test suite this scenario is filed in, or null when unfiled. Absent on servers that predate test suites."},"fields":{"type":"object","propertyNames":{"type":"string","maxLength":64},"additionalProperties":{"anyOf":[{"type":"string","maxLength":65536},{"type":"number"},{"type":"boolean"}]},"description":"The value this scenario carries for each field its test suite declares, keyed by field identifier. A field with no value has no key. Absent on servers that predate suite fields."},"platformUrl":{"type":"string","format":"uri"}},"required":["id","name","situation","criteria","labels","parameters","platformUrl"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Scenario not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]},"put":{"operationId":"putApiScenariosById","description":"Update an existing scenario","responses":{"200":{"description":"Scenario updated","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"situation":{"type":"string"},"criteria":{"type":"array","items":{"type":"string"}},"labels":{"type":"array","items":{"type":"string"}},"parameters":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","pattern":"^[A-Za-z_][A-Za-z0-9_]*$","minLength":1,"maxLength":64},"description":{"type":"string","maxLength":500},"defaultValue":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"secret":{"type":"boolean"},"type":{"type":"string","enum":["string","number","boolean"]},"options":{"type":"array","items":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"maxItems":50},"required":{"type":"boolean"}},"required":["name"]}},"simulatorModel":{"type":["string","null"],"description":"The model that plays the user, or null for the project default. Absent on servers that predate model overrides on this family."},"judgeModel":{"type":["string","null"],"description":"The model that judges the run, or null for the project default. Absent on servers that predate model overrides on this family."},"maxTurns":{"type":["integer","null"],"description":"The most conversation turns a run of this scenario takes, or null for the default. Absent on servers that predate turn limits on this family."},"minTurns":{"type":["integer","null"],"description":"The fewest conversation turns before the judge may end a run, or null for the default. Absent on servers that predate turn limits on this family."},"testSuiteId":{"type":["string","null"],"description":"The test suite this scenario is filed in, or null when unfiled. Absent on servers that predate test suites."},"fields":{"type":"object","propertyNames":{"type":"string","maxLength":64},"additionalProperties":{"anyOf":[{"type":"string","maxLength":65536},{"type":"number"},{"type":"boolean"}]},"description":"The value this scenario carries for each field its test suite declares, keyed by field identifier. A field with no value has no key. Absent on servers that predate suite fields."},"platformUrl":{"type":"string","format":"uri"}},"required":["id","name","situation","criteria","labels","parameters","platformUrl"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Scenario not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1},"situation":{"type":"string"},"criteria":{"type":"array","items":{"type":"string"}},"labels":{"type":"array","items":{"type":"string"}},"parameters":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","pattern":"^[A-Za-z_][A-Za-z0-9_]*$","minLength":1,"maxLength":64},"description":{"type":"string","maxLength":500},"defaultValue":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"secret":{"type":"boolean"},"type":{"type":"string","enum":["string","number","boolean"]},"options":{"type":"array","items":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"maxItems":50},"required":{"type":"boolean"}},"required":["name"]},"maxItems":20,"description":"The parameters this scenario declares by name, each with an optional description and default. A run supplies values for these names, readable from the scenario's own text as params.NAME. A parameter marked secret carries no default: its value is supplied per run, encrypted, delivered to the target as secrets.NAME, and never readable from the scenario's own text."},"simulatorModel":{"type":["string","null"],"pattern":"^[a-zA-Z0-9_-]+(?:\\/[^\\s/]+)+$","maxLength":200,"description":"Model for the simulated user, e.g. openai/gpt-5-mini. Null uses the project default."},"judgeModel":{"type":["string","null"],"pattern":"^[a-zA-Z0-9_-]+(?:\\/[^\\s/]+)+$","maxLength":200,"description":"Model for the judge, e.g. openai/gpt-5-mini. Null uses the project default."},"maxTurns":{"type":["integer","null"],"minimum":1,"maximum":100,"description":"Maximum conversation turns for a run of this scenario. Null uses the default."},"minTurns":{"type":["integer","null"],"minimum":0,"maximum":100,"description":"Minimum conversation turns before the judge may end the run. Null uses the default."},"testSuiteId":{"type":["string","null"],"description":"The test suite to file this scenario in. It must name a non-archived test suite of the same project. null files the scenario into the project's Default test suite."},"fields":{"type":"object","propertyNames":{"type":"string","maxLength":64},"additionalProperties":{"anyOf":[{"type":"string","maxLength":65536},{"type":"number"},{"type":"boolean"}]},"description":"The value for each field the test suite declares, keyed by field identifier: text, a number or a boolean, in the field's own type. A field the suite does not declare answers 422 scenario_field_unknown; a value of the wrong type answers 422 scenario_field_type_invalid. An empty value clears the field. Send the full record; an empty record clears every value."}},"additionalProperties":false}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]},"patch":{"operationId":"patchApiScenariosById","description":"Update an existing scenario","responses":{"200":{"description":"Scenario updated","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"situation":{"type":"string"},"criteria":{"type":"array","items":{"type":"string"}},"labels":{"type":"array","items":{"type":"string"}},"parameters":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","pattern":"^[A-Za-z_][A-Za-z0-9_]*$","minLength":1,"maxLength":64},"description":{"type":"string","maxLength":500},"defaultValue":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"secret":{"type":"boolean"},"type":{"type":"string","enum":["string","number","boolean"]},"options":{"type":"array","items":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"maxItems":50},"required":{"type":"boolean"}},"required":["name"]}},"simulatorModel":{"type":["string","null"],"description":"The model that plays the user, or null for the project default. Absent on servers that predate model overrides on this family."},"judgeModel":{"type":["string","null"],"description":"The model that judges the run, or null for the project default. Absent on servers that predate model overrides on this family."},"maxTurns":{"type":["integer","null"],"description":"The most conversation turns a run of this scenario takes, or null for the default. Absent on servers that predate turn limits on this family."},"minTurns":{"type":["integer","null"],"description":"The fewest conversation turns before the judge may end a run, or null for the default. Absent on servers that predate turn limits on this family."},"testSuiteId":{"type":["string","null"],"description":"The test suite this scenario is filed in, or null when unfiled. Absent on servers that predate test suites."},"fields":{"type":"object","propertyNames":{"type":"string","maxLength":64},"additionalProperties":{"anyOf":[{"type":"string","maxLength":65536},{"type":"number"},{"type":"boolean"}]},"description":"The value this scenario carries for each field its test suite declares, keyed by field identifier. A field with no value has no key. Absent on servers that predate suite fields."},"platformUrl":{"type":"string","format":"uri"}},"required":["id","name","situation","criteria","labels","parameters","platformUrl"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Scenario not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1},"situation":{"type":"string"},"criteria":{"type":"array","items":{"type":"string"}},"labels":{"type":"array","items":{"type":"string"}},"parameters":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","pattern":"^[A-Za-z_][A-Za-z0-9_]*$","minLength":1,"maxLength":64},"description":{"type":"string","maxLength":500},"defaultValue":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"secret":{"type":"boolean"},"type":{"type":"string","enum":["string","number","boolean"]},"options":{"type":"array","items":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"maxItems":50},"required":{"type":"boolean"}},"required":["name"]},"maxItems":20,"description":"The parameters this scenario declares by name, each with an optional description and default. A run supplies values for these names, readable from the scenario's own text as params.NAME. A parameter marked secret carries no default: its value is supplied per run, encrypted, delivered to the target as secrets.NAME, and never readable from the scenario's own text."},"simulatorModel":{"type":["string","null"],"pattern":"^[a-zA-Z0-9_-]+(?:\\/[^\\s/]+)+$","maxLength":200,"description":"Model for the simulated user, e.g. openai/gpt-5-mini. Null uses the project default."},"judgeModel":{"type":["string","null"],"pattern":"^[a-zA-Z0-9_-]+(?:\\/[^\\s/]+)+$","maxLength":200,"description":"Model for the judge, e.g. openai/gpt-5-mini. Null uses the project default."},"maxTurns":{"type":["integer","null"],"minimum":1,"maximum":100,"description":"Maximum conversation turns for a run of this scenario. Null uses the default."},"minTurns":{"type":["integer","null"],"minimum":0,"maximum":100,"description":"Minimum conversation turns before the judge may end the run. Null uses the default."},"testSuiteId":{"type":["string","null"],"description":"The test suite to file this scenario in. It must name a non-archived test suite of the same project. null files the scenario into the project's Default test suite."},"fields":{"type":"object","propertyNames":{"type":"string","maxLength":64},"additionalProperties":{"anyOf":[{"type":"string","maxLength":65536},{"type":"number"},{"type":"boolean"}]},"description":"The value for each field the test suite declares, keyed by field identifier: text, a number or a boolean, in the field's own type. A field the suite does not declare answers 422 scenario_field_unknown; a value of the wrong type answers 422 scenario_field_type_invalid. An empty value clears the field. Send the full record; an empty record clears every value."}},"additionalProperties":false}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]},"delete":{"operationId":"deleteApiScenariosById","description":"Archive (soft-delete) a scenario","responses":{"200":{"description":"Scenario archived","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"archived":{"type":"boolean"}},"required":["id","archived"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Scenario not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]}},"/api/scenarios/{id}/versions":{"get":{"operationId":"getApiScenariosByIdVersions","description":"List the saved versions of a scenario, newest first. A scenario saved before versions were recorded closes its history with a synthesized Created entry.","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"versions":{"type":"array","items":{"type":"object","properties":{"version":{"type":"integer","description":"The version number, counting from 1."},"authorLabel":{"type":["string","null"],"description":"Which surface wrote the version: user, api, cli or langy. Null on the synthesized Created entry of a scenario saved before versions were recorded."},"authorId":{"type":["string","null"],"description":"The user who saved the version. Null when the save came from an API key."},"changeDescription":{"type":["string","null"]},"changedFields":{"type":"array","items":{"type":"string"},"description":"The fields whose value this save changed."},"createdAt":{"type":"string","description":"When the version was written, in ISO 8601."},"isSynthesized":{"type":"boolean","description":"True on the Created entry a scenario saved before versions were recorded shows. It has no stored snapshot, so it cannot be read back."}},"required":["version","authorLabel","authorId","changeDescription","changedFields","createdAt","isSynthesized"]}},"nextCursor":{"type":["integer","null"],"description":"Pass as cursor to read the page below this one. Null on the last page."}},"required":["versions","nextCursor"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Scenario not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"parameters":[{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":100}},{"in":"query","name":"cursor","schema":{"type":"integer","minimum":1},"description":"Read the page below this version number."},{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]}},"/api/scenarios/{id}/versions/{version}":{"get":{"operationId":"getApiScenariosByIdVersionsByVersion","description":"Get one saved version of a scenario, with the name, situation, criteria, labels and parameters as that version saved them.","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"version":{"type":"integer","description":"The version number, counting from 1."},"authorLabel":{"type":["string","null"],"description":"Which surface wrote the version: user, api, cli or langy. Null on the synthesized Created entry of a scenario saved before versions were recorded."},"authorId":{"type":["string","null"],"description":"The user who saved the version. Null when the save came from an API key."},"changeDescription":{"type":["string","null"]},"changedFields":{"type":"array","items":{"type":"string"},"description":"The fields whose value this save changed."},"createdAt":{"type":"string","description":"When the version was written, in ISO 8601."},"isSynthesized":{"type":"boolean","description":"True on the Created entry a scenario saved before versions were recorded shows. It has no stored snapshot, so it cannot be read back."},"schemaVersion":{"type":"integer","description":"The shape the snapshot was written in."},"snapshot":{"type":"object","properties":{"name":{"type":"string"},"situation":{"type":"string"},"criteria":{"type":"array","items":{"type":"string"}},"labels":{"type":"array","items":{"type":"string"}},"parameters":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","pattern":"^[A-Za-z_][A-Za-z0-9_]*$","minLength":1,"maxLength":64},"description":{"type":"string","maxLength":500},"defaultValue":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"secret":{"type":"boolean"},"type":{"type":"string","enum":["string","number","boolean"]},"options":{"type":"array","items":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"maxItems":50},"required":{"type":"boolean"}},"required":["name"]}},"simulatorModel":{"type":["string","null"]},"judgeModel":{"type":["string","null"]},"maxTurns":{"type":["number","null"]},"minTurns":{"type":["number","null"]},"fields":{"type":"object","propertyNames":{"type":"string","maxLength":64},"additionalProperties":{"anyOf":[{"type":"string","maxLength":65536},{"type":"number"},{"type":"boolean"}]},"description":"The field values as this version saved them. Absent on servers that predate suite fields."}},"required":["name","situation","criteria","labels","parameters","simulatorModel","judgeModel","maxTurns","minTurns"],"description":"The editable content of the scenario as this version saved it."}},"required":["version","authorLabel","authorId","changeDescription","changedFields","createdAt","isSynthesized","schemaVersion","snapshot"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Scenario or version not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"parameters":[{"in":"path","name":"version","schema":{"type":"integer","minimum":1},"required":true},{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]}},"/api/projects":{"get":{"operationId":"listProjects","summary":"List projects","description":"List all non-archived projects for the organization (paginated). Requires an admin API key with project:view permission.","security":[{"admin_api_key":[]}],"parameters":[{"in":"query","name":"page","schema":{"type":"integer","exclusiveMinimum":0,"default":1}},{"in":"query","name":"limit","schema":{"type":"integer","exclusiveMinimum":0,"maximum":1000,"default":50}}],"responses":{"200":{"description":"Paginated list of projects","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Project"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}}}}},"401":{"description":"Invalid or missing API key token"},"403":{"description":"Insufficient permissions for this operation"}}},"post":{"operationId":"createProject","summary":"Create a project","description":"Create a new project in the organization. Returns the project with its API key (sk-lw-...) for sending traces. Provide either teamId (existing team) or newTeamName (creates a new team). Requires project:create permission.","security":[{"admin_api_key":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"description":"Project name"},"teamId":{"type":"string","minLength":1,"description":"Id of an existing team to put the project in"},"newTeamName":{"type":"string","minLength":1,"maxLength":255,"description":"Create a team with this name and put the project in it"},"language":{"type":"string","minLength":1,"description":"Programming language, such as python or typescript"},"framework":{"type":"string","minLength":1,"description":"Framework in use, such as langchain or openai"}},"required":["name","language","framework"]}}}},"responses":{"201":{"description":"Project created. Returns a scoped service API key for this project.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Project"},{"type":"object","properties":{"serviceApiKey":{"type":"string","description":"Scoped service API key with ADMIN on this project (sk-lw-..._...). Store securely — shown only once."},"serviceApiKeyId":{"type":"string","description":"ID of the auto-created service key, for management via DELETE /api/api-keys/{id}."}}}]}}}},"400":{"description":"Team does not belong to this organization"},"401":{"description":"Invalid or missing API key token"},"403":{"description":"Insufficient permissions (requires project:create)"},"409":{"description":"A project with this name already exists in the team"},"422":{"description":"Validation error (missing required fields)"}}}},"/api/projects/{id}":{"get":{"operationId":"getProject","summary":"Get a project","description":"Get a project by ID without secret keys. Requires project:view permission.","security":[{"admin_api_key":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Project ID (project_...)"}],"responses":{"200":{"description":"Project details.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Project"}}}},"401":{"description":"Invalid or missing API key token"},"403":{"description":"Insufficient permissions for this operation"},"404":{"description":"Project not found"}}},"patch":{"operationId":"updateProject","summary":"Update a project","description":"Update project fields. Only provided fields are changed. Requires project:update permission.","security":[{"admin_api_key":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Project ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"language":{"type":"string"},"framework":{"type":"string"},"teamId":{"type":"string","minLength":1,"description":"Moves the project to this team"}}}}}},"responses":{"200":{"description":"Updated project","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Project"}}}},"401":{"description":"Invalid or missing API key token"},"403":{"description":"Insufficient permissions (requires project:update)"},"404":{"description":"Project not found"}}},"delete":{"operationId":"archiveProject","summary":"Archive a project","description":"Soft-delete (archive) a project. Archived projects are excluded from list responses. Requires project:delete permission.","security":[{"admin_api_key":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Project ID"}],"responses":{"200":{"description":"Project archived","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"archivedAt":{"type":"string","format":"date-time"}}}}}},"401":{"description":"Invalid or missing API key token"},"403":{"description":"Insufficient permissions (requires project:delete)"},"404":{"description":"Project not found"}}}},"/api/projects/{id}/api-key":{"get":{"operationId":"getProjectApiKey","summary":"Get the project API key","deprecated":true,"description":"Deprecated. Project base keys can be revealed only by a signed-in project administrator in the browser or an approved device flow. Organization API keys are always refused with 403.","security":[{"admin_api_key":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"},"description":"Project id"}],"responses":{"401":{"description":"Invalid or missing API key token"},"403":{"description":"A signed-in project administrator is required; API-key principals cannot reveal base keys"}}}},"/api/projects/{id}/regenerate-api-key":{"post":{"operationId":"regenerateProjectApiKey","summary":"Regenerate the project API key","deprecated":true,"description":"Deprecated. Project base keys can be rotated only by a signed-in project administrator in the browser. Organization API keys are always refused with 403.","security":[{"admin_api_key":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"},"description":"Project id"}],"responses":{"401":{"description":"Invalid or missing API key token"},"403":{"description":"A signed-in project administrator is required; API-key principals cannot rotate base keys"}}}},"/api/secrets":{"get":{"operationId":"getApiSecrets","description":"List all secrets for the project (values are never returned)","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"projectId":{"type":"string"},"name":{"type":"string"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","projectId","name","createdAt","updatedAt"]}}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"security":[{"project_api_key":[]}]},"post":{"operationId":"postApiSecrets","description":"Create a new project secret. The value is encrypted at rest and never returned.","responses":{"201":{"description":"Secret created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"projectId":{"type":"string"},"name":{"type":"string"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","projectId","name","createdAt","updatedAt"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"409":{"description":"Secret with this name already exists","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","pattern":"^[A-Z][A-Z0-9_]*$","minLength":1},"value":{"type":"string","minLength":1,"maxLength":10000}},"required":["name","value"]}}}},"security":[{"project_api_key":[]}]}},"/api/secrets/{id}":{"get":{"operationId":"getApiSecretsById","description":"Get a secret by its ID (value is never returned)","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"projectId":{"type":"string"},"name":{"type":"string"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","projectId","name","createdAt","updatedAt"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Secret not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]},"put":{"operationId":"putApiSecretsById","description":"Update a secret's value","responses":{"200":{"description":"Secret updated","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"projectId":{"type":"string"},"name":{"type":"string"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","projectId","name","createdAt","updatedAt"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Secret not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"value":{"type":"string","minLength":1,"maxLength":10000}},"required":["value"]}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]},"delete":{"operationId":"deleteApiSecretsById","description":"Delete a secret","responses":{"200":{"description":"Secret deleted","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"deleted":{"type":"boolean"}},"required":["id","deleted"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Secret not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]}},"/api/simulation-runs":{"get":{"operationId":"getApiSimulationRuns","description":"List simulation runs, optionally filtered by scenarioSetId or batchRunId. Set-level and unfiltered listings trim each run to its first few messages and report the trim as `messagesTruncated`; pass `include=messages` to read whole conversations, which caps the page at 20 runs, ending on a batch boundary. A batch-scoped listing always carries whole conversations.","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"runs":{"type":"array","items":{"type":"object","properties":{"scenarioId":{"type":"string"},"batchRunId":{"type":"string"},"scenarioRunId":{"type":"string"},"name":{"type":["string","null"]},"description":{"type":["string","null"]},"status":{"type":"string","description":"Where the run stands. PENDING_EVALUATION means the conversation is over and the judge has decided, but the evaluators the run's suite and plan attach have not been recorded yet, so a required one may still fail the run. Wait for another status before reading the verdict as final."},"results":{"type":["object","null"],"properties":{"verdict":{"type":["string","null"]},"reasoning":{"type":["string","null"]},"metCriteria":{"type":"array","items":{"type":"string"}},"unmetCriteria":{"type":"array","items":{"type":"string"}},"error":{"type":["string","null"]},"evaluations":{"type":"array","items":{"type":"object","properties":{"evaluatorId":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","enum":["passed","failed","scored","skipped","error"]},"required":{"type":"boolean"},"passed":{"type":"boolean"},"score":{"type":"number"},"label":{"type":"string"},"details":{"type":"string"},"cost":{"type":"object","properties":{"currency":{"type":"string"},"amount":{"type":"number"}},"required":["currency","amount"]},"inputs":{"type":"object","additionalProperties":{"type":"string"}}},"required":["evaluatorId","name","status","required"]},"description":"One result per evaluator that ran on the scenario. Absent on a run with no evaluators, and on servers that predate evaluators."}}},"messages":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string"},"content":{"type":"string"}},"required":["role","content"]}},"messagesTruncated":{"type":"boolean","description":"True when `messages` holds only the first few messages of a longer conversation. Pass `include=messages` to read them all."},"timestamp":{"type":"number"},"updatedAt":{"type":"number"},"durationInMs":{"type":"number"},"totalCost":{"type":"number"},"note":{"type":["string","null"],"description":"One short line saying why the run was started, as given when it was queued. Null on a run started without one. Absent on servers that predate run notes."},"scenarioVersion":{"type":["integer","null"],"description":"The version of the scenario at the moment the run was queued. Null on runs recorded before versions existed. Absent on servers that predate scenario versions."},"platformUrl":{"type":"string","format":"uri"}},"required":["scenarioId","batchRunId","scenarioRunId","name","description","status","results","messages","timestamp","updatedAt","durationInMs","platformUrl"]}},"hasMore":{"type":"boolean"},"nextCursor":{"type":"string"}},"required":["runs"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"parameters":[{"in":"query","name":"scenarioSetId","schema":{"type":"string"}},{"in":"query","name":"batchRunId","schema":{"type":"string"}},{"in":"query","name":"limit","schema":{"type":"integer","exclusiveMinimum":0,"maximum":100,"default":20}},{"in":"query","name":"cursor","schema":{"type":"string"}},{"in":"query","name":"include","schema":{"type":"string","const":"messages"},"description":"Pass `messages` to read whole conversations instead of the first few messages of each run. The page size is capped at 20 runs when set, and ends on a batch boundary."}],"security":[{"project_api_key":[]}]}},"/api/simulation-runs/{scenarioRunId}":{"get":{"operationId":"getApiSimulationRunsByScenarioRunId","description":"Get a single simulation run by its ID","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"scenarioId":{"type":"string"},"batchRunId":{"type":"string"},"scenarioRunId":{"type":"string"},"name":{"type":["string","null"]},"description":{"type":["string","null"]},"status":{"type":"string","description":"Where the run stands. PENDING_EVALUATION means the conversation is over and the judge has decided, but the evaluators the run's suite and plan attach have not been recorded yet, so a required one may still fail the run. Wait for another status before reading the verdict as final."},"results":{"type":["object","null"],"properties":{"verdict":{"type":["string","null"]},"reasoning":{"type":["string","null"]},"metCriteria":{"type":"array","items":{"type":"string"}},"unmetCriteria":{"type":"array","items":{"type":"string"}},"error":{"type":["string","null"]},"evaluations":{"type":"array","items":{"type":"object","properties":{"evaluatorId":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","enum":["passed","failed","scored","skipped","error"]},"required":{"type":"boolean"},"passed":{"type":"boolean"},"score":{"type":"number"},"label":{"type":"string"},"details":{"type":"string"},"cost":{"type":"object","properties":{"currency":{"type":"string"},"amount":{"type":"number"}},"required":["currency","amount"]},"inputs":{"type":"object","additionalProperties":{"type":"string"}}},"required":["evaluatorId","name","status","required"]},"description":"One result per evaluator that ran on the scenario. Absent on a run with no evaluators, and on servers that predate evaluators."}}},"messages":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string"},"content":{"type":"string"}},"required":["role","content"]}},"messagesTruncated":{"type":"boolean","description":"True when `messages` holds only the first few messages of a longer conversation. Pass `include=messages` to read them all."},"timestamp":{"type":"number"},"updatedAt":{"type":"number"},"durationInMs":{"type":"number"},"totalCost":{"type":"number"},"note":{"type":["string","null"],"description":"One short line saying why the run was started, as given when it was queued. Null on a run started without one. Absent on servers that predate run notes."},"scenarioVersion":{"type":["integer","null"],"description":"The version of the scenario at the moment the run was queued. Null on runs recorded before versions existed. Absent on servers that predate scenario versions."},"platformUrl":{"type":"string","format":"uri"}},"required":["scenarioId","batchRunId","scenarioRunId","name","description","status","results","messages","timestamp","updatedAt","durationInMs","platformUrl"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Run not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"scenarioRunId","required":true}],"security":[{"project_api_key":[]}]}},"/api/simulation-runs/batches/list":{"get":{"operationId":"getApiSimulationRunsBatchesList","description":"List batch summaries for a scenario set (pass/fail counts per batch)","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"batches":{"type":"array","items":{"type":"object","properties":{"batchRunId":{"type":"string"},"totalCount":{"type":"number"},"passCount":{"type":"number"},"failCount":{"type":"number"},"runningCount":{"type":"number"},"settledCount":{"type":"number"},"stalledCount":{"type":"number"},"lastRunAt":{"type":"number"},"lastUpdatedAt":{"type":"number"},"firstCompletedAt":{"type":["number","null"]},"allCompletedAt":{"type":["number","null"],"description":"Deprecated: read settledCount and isComplete instead. It carries the last update time of a batch where no run is running.","deprecated":true},"isComplete":{"type":"boolean","description":"True when every run of the batch reached a terminal status."},"note":{"type":["string","null"],"description":"One short line saying why the batch was run, as given when it was queued. Null on a batch run without one. Absent on servers that predate run notes."}},"required":["batchRunId","totalCount","passCount","failCount","runningCount","settledCount","stalledCount","lastRunAt","lastUpdatedAt","firstCompletedAt","allCompletedAt","isComplete"]}},"hasMore":{"type":"boolean"},"nextCursor":{"type":"string"}},"required":["batches"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"parameters":[{"in":"query","name":"scenarioSetId","schema":{"type":"string"},"required":true},{"in":"query","name":"limit","schema":{"type":"integer","exclusiveMinimum":0,"maximum":50,"default":10}},{"in":"query","name":"cursor","schema":{"type":"string"}}],"security":[{"project_api_key":[]}]}},"/api/simulation-runs/batches/{batchRunId}":{"get":{"operationId":"getApiSimulationRunsBatchesByBatchRunId","description":"Get the summary of a single batch run, including its completion flag","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"batchRunId":{"type":"string"},"totalCount":{"type":"number"},"passCount":{"type":"number"},"failCount":{"type":"number"},"runningCount":{"type":"number"},"settledCount":{"type":"number"},"stalledCount":{"type":"number"},"lastRunAt":{"type":"number"},"lastUpdatedAt":{"type":"number"},"firstCompletedAt":{"type":["number","null"]},"allCompletedAt":{"type":["number","null"],"description":"Deprecated: read settledCount and isComplete instead. It carries the last update time of a batch where no run is running.","deprecated":true},"isComplete":{"type":"boolean","description":"True when every run of the batch reached a terminal status."},"note":{"type":["string","null"],"description":"One short line saying why the batch was run, as given when it was queued. Null on a batch run without one. Absent on servers that predate run notes."}},"required":["batchRunId","totalCount","passCount","failCount","runningCount","settledCount","stalledCount","lastRunAt","lastUpdatedAt","firstCompletedAt","allCompletedAt","isComplete"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Batch run not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"batchRunId","required":true}],"security":[{"project_api_key":[]}]}},"/api/suites":{"get":{"operationId":"getApiSuites","deprecated":true,"description":"Deprecated: use /api/v1/run-plans and /api/v1/test-suites. List all non-archived suites for the project. By default only run plans are returned; pass kind=folder for test suites.","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"kind":{"type":"string","enum":["custom","folder"],"description":"custom is a hand-assembled run plan; folder is a test suite that groups scenarios filed into it. Absent on servers that predate test suites."},"description":{"type":["string","null"]},"scenarioIds":{"type":"array","items":{"type":"string"}},"scope":{"oneOf":[{"type":"object","properties":{"mode":{"type":"string","const":"all"}},"required":["mode"]},{"type":"object","properties":{"mode":{"type":"string","const":"folders"},"folderIds":{"type":"array","items":{"type":"string"}}},"required":["mode","folderIds"]},{"type":"object","properties":{"mode":{"type":"string","const":"labels"},"labels":{"type":"array","items":{"type":"string"}}},"required":["mode","labels"]},{"type":"object","properties":{"mode":{"type":"string","const":"cases"}},"required":["mode"]},{"type":"null"}],"description":"What the run plan covers: all (every active scenario), folders (the scenarios filed in the named test suites), labels (the scenarios carrying any of the labels), or cases (the scenarioIds below). A dynamic scope is resolved again at every run, so a scenario written later runs without editing the plan."},"targets":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["prompt","http","code","workflow","connected","voice"],"description":"What kind of thing the scenarios run against. A connected agent is one registered from code with the SDK."},"referenceId":{"type":"string","description":"The id of the prompt, agent or workflow to run against. A connected target may also say <name>@<environment>, for example support-agent@production, which resolves to the agent id."},"runParameters":{"type":"object","additionalProperties":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"description":"Parameter values this target alone runs with, by name. They are merged over the run-level parameters and the target wins, so two targets may name the same agent with different values: that is how one run compares one agent on two models, and the results show one column for each target."}},"required":["type","referenceId"]}},"repeatCount":{"type":"number"},"labels":{"type":"array","items":{"type":"string"}},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"platformUrl":{"type":"string","format":"uri"}},"required":["id","name","slug","description","scenarioIds","targets","repeatCount","labels","createdAt","updatedAt","platformUrl"]}}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"parameters":[{"in":"query","name":"kind","schema":{"type":"string","enum":["custom","folder"],"default":"custom"},"description":"Which kind of suite to list. Defaults to custom, so callers that predate test suites keep seeing exactly the run plans they always did."}],"security":[{"project_api_key":[]}]},"post":{"operationId":"postApiSuites","deprecated":true,"description":"Deprecated: use /api/v1/run-plans and /api/v1/test-suites. Create a new suite (run plan).","responses":{"201":{"description":"Suite created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"kind":{"type":"string","enum":["custom","folder"],"description":"custom is a hand-assembled run plan; folder is a test suite that groups scenarios filed into it. Absent on servers that predate test suites."},"description":{"type":["string","null"]},"scenarioIds":{"type":"array","items":{"type":"string"}},"scope":{"oneOf":[{"type":"object","properties":{"mode":{"type":"string","const":"all"}},"required":["mode"]},{"type":"object","properties":{"mode":{"type":"string","const":"folders"},"folderIds":{"type":"array","items":{"type":"string"}}},"required":["mode","folderIds"]},{"type":"object","properties":{"mode":{"type":"string","const":"labels"},"labels":{"type":"array","items":{"type":"string"}}},"required":["mode","labels"]},{"type":"object","properties":{"mode":{"type":"string","const":"cases"}},"required":["mode"]},{"type":"null"}],"description":"What the run plan covers: all (every active scenario), folders (the scenarios filed in the named test suites), labels (the scenarios carrying any of the labels), or cases (the scenarioIds below). A dynamic scope is resolved again at every run, so a scenario written later runs without editing the plan."},"targets":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["prompt","http","code","workflow","connected","voice"],"description":"What kind of thing the scenarios run against. A connected agent is one registered from code with the SDK."},"referenceId":{"type":"string","description":"The id of the prompt, agent or workflow to run against. A connected target may also say <name>@<environment>, for example support-agent@production, which resolves to the agent id."},"runParameters":{"type":"object","additionalProperties":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"description":"Parameter values this target alone runs with, by name. They are merged over the run-level parameters and the target wins, so two targets may name the same agent with different values: that is how one run compares one agent on two models, and the results show one column for each target."}},"required":["type","referenceId"]}},"repeatCount":{"type":"number"},"labels":{"type":"array","items":{"type":"string"}},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"platformUrl":{"type":"string","format":"uri"}},"required":["id","name","slug","description","scenarioIds","targets","repeatCount","labels","createdAt","updatedAt","platformUrl"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1},"kind":{"type":"string","enum":["custom","folder"],"default":"custom","description":"custom (the default) is a run plan and needs scenarioIds and targets; folder is a test suite that starts empty and gets scenarios by filing them into it."},"description":{"type":"string"},"scenarioIds":{"type":"array","items":{"type":"string"},"default":[]},"scope":{"oneOf":[{"type":"object","properties":{"mode":{"type":"string","const":"all"}},"required":["mode"]},{"type":"object","properties":{"mode":{"type":"string","const":"folders"},"folderIds":{"type":"array","items":{"type":"string"}}},"required":["mode","folderIds"]},{"type":"object","properties":{"mode":{"type":"string","const":"labels"},"labels":{"type":"array","items":{"type":"string"}}},"required":["mode","labels"]},{"type":"object","properties":{"mode":{"type":"string","const":"cases"}},"required":["mode"]}],"description":"What the run plan covers: all (every active scenario), folders (the scenarios filed in the named test suites), labels (the scenarios carrying any of the labels), or cases (the scenarioIds below). A dynamic scope is resolved again at every run, so a scenario written later runs without editing the plan."},"targets":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["prompt","http","code","workflow","connected","voice"],"description":"What kind of thing the scenarios run against. A connected agent is one registered from code with the SDK."},"referenceId":{"type":"string","description":"The id of the prompt, agent or workflow to run against. A connected target may also say <name>@<environment>, for example support-agent@production, which resolves to the agent id."},"runParameters":{"type":"object","additionalProperties":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"description":"Parameter values this target alone runs with, by name. They are merged over the run-level parameters and the target wins, so two targets may name the same agent with different values: that is how one run compares one agent on two models, and the results show one column for each target."}},"required":["type","referenceId"]},"default":[]},"repeatCount":{"type":"integer","minimum":1,"maximum":100,"default":1},"labels":{"type":"array","items":{"type":"string"},"default":[]}},"required":["name"],"additionalProperties":false}}}},"security":[{"project_api_key":[]}]}},"/api/suites/{id}":{"get":{"operationId":"getApiSuitesById","deprecated":true,"description":"Deprecated: use /api/v1/run-plans and /api/v1/test-suites. Get a suite (run plan) by its ID.","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"kind":{"type":"string","enum":["custom","folder"],"description":"custom is a hand-assembled run plan; folder is a test suite that groups scenarios filed into it. Absent on servers that predate test suites."},"description":{"type":["string","null"]},"scenarioIds":{"type":"array","items":{"type":"string"}},"scope":{"oneOf":[{"type":"object","properties":{"mode":{"type":"string","const":"all"}},"required":["mode"]},{"type":"object","properties":{"mode":{"type":"string","const":"folders"},"folderIds":{"type":"array","items":{"type":"string"}}},"required":["mode","folderIds"]},{"type":"object","properties":{"mode":{"type":"string","const":"labels"},"labels":{"type":"array","items":{"type":"string"}}},"required":["mode","labels"]},{"type":"object","properties":{"mode":{"type":"string","const":"cases"}},"required":["mode"]},{"type":"null"}],"description":"What the run plan covers: all (every active scenario), folders (the scenarios filed in the named test suites), labels (the scenarios carrying any of the labels), or cases (the scenarioIds below). A dynamic scope is resolved again at every run, so a scenario written later runs without editing the plan."},"targets":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["prompt","http","code","workflow","connected","voice"],"description":"What kind of thing the scenarios run against. A connected agent is one registered from code with the SDK."},"referenceId":{"type":"string","description":"The id of the prompt, agent or workflow to run against. A connected target may also say <name>@<environment>, for example support-agent@production, which resolves to the agent id."},"runParameters":{"type":"object","additionalProperties":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"description":"Parameter values this target alone runs with, by name. They are merged over the run-level parameters and the target wins, so two targets may name the same agent with different values: that is how one run compares one agent on two models, and the results show one column for each target."}},"required":["type","referenceId"]}},"repeatCount":{"type":"number"},"labels":{"type":"array","items":{"type":"string"}},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"platformUrl":{"type":"string","format":"uri"}},"required":["id","name","slug","description","scenarioIds","targets","repeatCount","labels","createdAt","updatedAt","platformUrl"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Suite not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"},"code":{"type":"string","description":"The domain error code, when the refusal names one."}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]},"patch":{"operationId":"patchApiSuitesById","deprecated":true,"description":"Deprecated: use /api/v1/run-plans and /api/v1/test-suites. Update a suite (run plan).","responses":{"200":{"description":"Suite updated","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"kind":{"type":"string","enum":["custom","folder"],"description":"custom is a hand-assembled run plan; folder is a test suite that groups scenarios filed into it. Absent on servers that predate test suites."},"description":{"type":["string","null"]},"scenarioIds":{"type":"array","items":{"type":"string"}},"scope":{"oneOf":[{"type":"object","properties":{"mode":{"type":"string","const":"all"}},"required":["mode"]},{"type":"object","properties":{"mode":{"type":"string","const":"folders"},"folderIds":{"type":"array","items":{"type":"string"}}},"required":["mode","folderIds"]},{"type":"object","properties":{"mode":{"type":"string","const":"labels"},"labels":{"type":"array","items":{"type":"string"}}},"required":["mode","labels"]},{"type":"object","properties":{"mode":{"type":"string","const":"cases"}},"required":["mode"]},{"type":"null"}],"description":"What the run plan covers: all (every active scenario), folders (the scenarios filed in the named test suites), labels (the scenarios carrying any of the labels), or cases (the scenarioIds below). A dynamic scope is resolved again at every run, so a scenario written later runs without editing the plan."},"targets":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["prompt","http","code","workflow","connected","voice"],"description":"What kind of thing the scenarios run against. A connected agent is one registered from code with the SDK."},"referenceId":{"type":"string","description":"The id of the prompt, agent or workflow to run against. A connected target may also say <name>@<environment>, for example support-agent@production, which resolves to the agent id."},"runParameters":{"type":"object","additionalProperties":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"description":"Parameter values this target alone runs with, by name. They are merged over the run-level parameters and the target wins, so two targets may name the same agent with different values: that is how one run compares one agent on two models, and the results show one column for each target."}},"required":["type","referenceId"]}},"repeatCount":{"type":"number"},"labels":{"type":"array","items":{"type":"string"}},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"platformUrl":{"type":"string","format":"uri"}},"required":["id","name","slug","description","scenarioIds","targets","repeatCount","labels","createdAt","updatedAt","platformUrl"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Suite not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"},"code":{"type":"string","description":"The domain error code, when the refusal names one."}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1},"description":{"type":["string","null"]},"scope":{"oneOf":[{"type":"object","properties":{"mode":{"type":"string","const":"all"}},"required":["mode"]},{"type":"object","properties":{"mode":{"type":"string","const":"folders"},"folderIds":{"type":"array","items":{"type":"string"}}},"required":["mode","folderIds"]},{"type":"object","properties":{"mode":{"type":"string","const":"labels"},"labels":{"type":"array","items":{"type":"string"}}},"required":["mode","labels"]},{"type":"object","properties":{"mode":{"type":"string","const":"cases"}},"required":["mode"]}],"description":"What the run plan covers: all (every active scenario), folders (the scenarios filed in the named test suites), labels (the scenarios carrying any of the labels), or cases (the scenarioIds below). A dynamic scope is resolved again at every run, so a scenario written later runs without editing the plan."},"scenarioIds":{"type":"array","items":{"type":"string"},"minItems":1},"targets":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["prompt","http","code","workflow","connected","voice"],"description":"What kind of thing the scenarios run against. A connected agent is one registered from code with the SDK."},"referenceId":{"type":"string","description":"The id of the prompt, agent or workflow to run against. A connected target may also say <name>@<environment>, for example support-agent@production, which resolves to the agent id."},"runParameters":{"type":"object","additionalProperties":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"description":"Parameter values this target alone runs with, by name. They are merged over the run-level parameters and the target wins, so two targets may name the same agent with different values: that is how one run compares one agent on two models, and the results show one column for each target."}},"required":["type","referenceId"]},"minItems":1},"repeatCount":{"type":"integer","minimum":1,"maximum":100},"labels":{"type":"array","items":{"type":"string"}}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]},"delete":{"operationId":"deleteApiSuitesById","deprecated":true,"description":"Deprecated: use /api/v1/run-plans and /api/v1/test-suites. Archive (soft-delete) a suite. Archiving a folder also archives every scenario filed in it, in one transaction.","responses":{"200":{"description":"Suite archived","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"archived":{"type":"boolean"}},"required":["id","archived"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Suite not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"},"code":{"type":"string","description":"The domain error code, when the refusal names one."}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]}},"/api/suites/{id}/duplicate":{"post":{"operationId":"postApiSuitesByIdDuplicate","deprecated":true,"description":"Deprecated: use /api/v1/run-plans and /api/v1/test-suites. Duplicate a suite (run plan).","responses":{"201":{"description":"Suite duplicated","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"kind":{"type":"string","enum":["custom","folder"],"description":"custom is a hand-assembled run plan; folder is a test suite that groups scenarios filed into it. Absent on servers that predate test suites."},"description":{"type":["string","null"]},"scenarioIds":{"type":"array","items":{"type":"string"}},"scope":{"oneOf":[{"type":"object","properties":{"mode":{"type":"string","const":"all"}},"required":["mode"]},{"type":"object","properties":{"mode":{"type":"string","const":"folders"},"folderIds":{"type":"array","items":{"type":"string"}}},"required":["mode","folderIds"]},{"type":"object","properties":{"mode":{"type":"string","const":"labels"},"labels":{"type":"array","items":{"type":"string"}}},"required":["mode","labels"]},{"type":"object","properties":{"mode":{"type":"string","const":"cases"}},"required":["mode"]},{"type":"null"}],"description":"What the run plan covers: all (every active scenario), folders (the scenarios filed in the named test suites), labels (the scenarios carrying any of the labels), or cases (the scenarioIds below). A dynamic scope is resolved again at every run, so a scenario written later runs without editing the plan."},"targets":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["prompt","http","code","workflow","connected","voice"],"description":"What kind of thing the scenarios run against. A connected agent is one registered from code with the SDK."},"referenceId":{"type":"string","description":"The id of the prompt, agent or workflow to run against. A connected target may also say <name>@<environment>, for example support-agent@production, which resolves to the agent id."},"runParameters":{"type":"object","additionalProperties":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"description":"Parameter values this target alone runs with, by name. They are merged over the run-level parameters and the target wins, so two targets may name the same agent with different values: that is how one run compares one agent on two models, and the results show one column for each target."}},"required":["type","referenceId"]}},"repeatCount":{"type":"number"},"labels":{"type":"array","items":{"type":"string"}},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"platformUrl":{"type":"string","format":"uri"}},"required":["id","name","slug","description","scenarioIds","targets","repeatCount","labels","createdAt","updatedAt","platformUrl"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Suite not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"},"code":{"type":"string","description":"The domain error code, when the refusal names one."}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]}},"/api/suites/{id}/run":{"post":{"operationId":"postApiSuitesByIdRun","deprecated":true,"description":"Deprecated: use /api/v1/run-plans and /api/v1/test-suites. Trigger a suite run. Schedules scenario executions for all active scenarios x targets x repeatCount. When the id names a test suite, the targets, the repeat count and the models are read from the body.","responses":{"200":{"description":"Suite run scheduled","content":{"application/json":{"schema":{"type":"object","properties":{"scheduled":{"type":"boolean"},"batchRunId":{"type":"string"},"setId":{"type":"string"},"jobCount":{"type":"number"},"skippedArchived":{"type":"object","properties":{"scenarios":{"type":"array","items":{"type":"string"}},"targets":{"type":"array","items":{"type":"string"}}},"required":["scenarios","targets"]},"items":{"type":"array","items":{"type":"object","properties":{"scenarioRunId":{"type":"string"},"scenarioId":{"type":"string"},"target":{"type":"object","properties":{"type":{"type":"string","enum":["prompt","http","code","workflow","connected","voice"],"description":"What kind of thing the scenarios run against. A connected agent is one registered from code with the SDK."},"referenceId":{"type":"string","description":"The id of the prompt, agent or workflow to run against. A connected target may also say <name>@<environment>, for example support-agent@production, which resolves to the agent id."},"runParameters":{"type":"object","additionalProperties":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"description":"Parameter values this target alone runs with, by name. They are merged over the run-level parameters and the target wins, so two targets may name the same agent with different values: that is how one run compares one agent on two models, and the results show one column for each target."}},"required":["type","referenceId"]},"name":{"type":["string","null"]}},"required":["scenarioRunId","scenarioId","target","name"]}}},"required":["scheduled","batchRunId","setId","jobCount","skippedArchived","items"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Suite not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"},"code":{"type":"string","description":"The domain error code, when the refusal names one."}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"idempotencyKey":{"type":"string"},"name":{"type":"string","minLength":1,"maxLength":200,"description":"The run plan this run joins or creates. Used only when the id names a test suite; derived from the suite name and the targets when absent."},"targets":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["prompt","http","code","workflow","connected","voice"],"description":"What kind of thing the scenarios run against. A connected agent is one registered from code with the SDK."},"referenceId":{"type":"string","description":"The id of the prompt, agent or workflow to run against. A connected target may also say <name>@<environment>, for example support-agent@production, which resolves to the agent id."},"runParameters":{"type":"object","additionalProperties":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"description":"Parameter values this target alone runs with, by name. They are merged over the run-level parameters and the target wins, so two targets may name the same agent with different values: that is how one run compares one agent on two models, and the results show one column for each target."}},"required":["type","referenceId"]},"description":"The prompts, agents or workflows the run goes against. Used only when the id names a test suite, which stores no target of its own."},"repeatCount":{"type":"integer","minimum":1,"maximum":5,"description":"How many times each scenario and target pairing runs, between 1 and 5. Used only when the id names a test suite."},"simulatorModel":{"type":["string","null"],"description":"The model that plays the user for every scenario in the run. Used only when the id names a test suite."},"judgeModel":{"type":["string","null"],"description":"The model that judges every scenario in the run. Used only when the id names a test suite."},"parameters":{"type":"object","additionalProperties":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"description":"Constant values applied to every scenario in the run, e.g. a fixture id or a tenant. A value supplied here overrides the scenario's own default for that name."},"note":{"type":"string","maxLength":200,"description":"One short line describing why this batch was run, e.g. a commit hash or what you changed. It is stored on every run of the batch and shown beside the run in the platform. Up to 200 characters."}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]}},"/api/v1/instant-evals":{"post":{"operationId":"createInstantEvalRun","responses":{"202":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"The run id."},"name":{"type":["string","null"],"description":"What the run was called, if anything."},"sql":{"type":"string","description":"The statement, exactly as submitted."},"parameters":{"type":"object","additionalProperties":{"anyOf":[{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"null"}]},{"type":"array","items":{"type":"string"}}]},"description":"The values the statement's parameters were filled with."},"questions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The statement's own output column, which is the name this question is addressed by everywhere else."},"function":{"type":"string","description":"The eval function that asked it."},"kind":{"type":"string","enum":["boolean","score","category"],"description":"What kind of answer the question takes."},"reads":{"type":"string","description":"Which part of the verdict the statement's column carries."},"threshold":{"type":["number","null"],"description":"Where a boolean question's probability becomes a pass. Null for a question that is not a boolean."}},"required":["id","function","kind","reads","threshold"]},"description":"One entry per eval function the statement projects, derived from it when the run was accepted."},"limit":{"type":"integer","description":"Rows this run may judge."},"status":{"type":"string","enum":["queued","planning","running","finished","failed","cancelled"],"description":"Where the run is in its life."},"total":{"type":["integer","null"],"description":"Rows the run found, bounded by its limit. Null until it has looked."},"progress":{"type":"integer","description":"Rows judged so far."},"matched":{"type":["integer","null"],"description":"Judgements that matched, across this run's boolean questions. Null when the run asked none: a score or a category question has no match to count."},"matchedByQuestion":{"type":"object","additionalProperties":{"type":"number"},"description":"Per question: matches for a boolean question, judged rows for a score or a category one."},"failed":{"type":"integer","description":"Rows the judge could not answer."},"skipped":{"type":"integer","description":"Rows the judge declined to answer."},"tokens":{"type":"integer","description":"Input tokens the judge billed for."},"priceUsd":{"type":"number","description":"What the judging costs you, in United States dollars."},"error":{"type":["string","null"],"description":"The code of the failure that ended the run, when one did."},"createdAt":{"type":"string","description":"When the run was accepted."},"updatedAt":{"type":"string","description":"When the run was last written to."},"startedAt":{"type":["string","null"],"description":"When the run began reading rows."},"finishedAt":{"type":["string","null"],"description":"When the run ended."}},"required":["id","name","sql","parameters","questions","limit","status","total","progress","matched","matchedByQuestion","failed","skipped","tokens","priceUsd","error","createdAt","updatedAt","startedAt","finishedAt"]}}}}},"description":"Start a run. The statement is accepted, its questions are derived from the eval functions it projects, and the judging happens on the queue: the answer is the queued run, and its progress is read back from the run endpoint. A statement the query policy refuses, one that projects no TraceId, one that projects no eval function, and a row limit past what the plan allows are all refused before anything is judged. Instead of a statement you may send a target and your questions, and the statement is written for you and handed back on the run; sending both is refused.","tags":["Instant Evals"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sql":{"type":"string","minLength":1,"maxLength":50000,"description":"The LangWatchQL statement to judge. It must project TraceId and at least one eval function column. Send this or target, never both."},"parameters":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"null"}]},"description":"Values for the parameters the statement declares."},"target":{"type":"string","enum":["traces","threads","llm_spans"],"description":"What one judged row is, in place of a statement: a trace, a conversation, or one model call. The statement is written for you from this and the questions, and handed back on the run so you can edit it and resubmit."},"filter":{"type":"string","maxLength":4000,"description":"With target: a trace filter, in the language the trace explorer's search bar speaks, narrowing which rows are judged."},"start":{"type":"string","format":"date-time","description":"With target: the oldest instant to judge, as an ISO 8601 timestamp. Defaults to seven days ago."},"end":{"type":"string","format":"date-time","description":"With target: the newest instant to judge. Defaults to now."},"questions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64,"description":"What to call this question. It becomes the statement's output column and the name every judgement is filed under. Defaults to q1, q2 and so on."},"kind":{"type":"string","enum":["boolean","score","category"],"default":"boolean","description":"What kind of answer you want: a yes or no, a rating on a scale, or one of a list of options."},"instructions":{"type":"string","minLength":1,"maxLength":2000,"description":"The question, in your own words, as you would write it for a human reader."},"criteria":{"type":"array","items":{"type":"string","minLength":1,"maxLength":500},"minItems":2,"maxItems":2,"description":"For a yes or no question: what counts as yes, then what counts as no. Cannot be combined with a threshold."},"threshold":{"type":"number","minimum":0,"maximum":1,"description":"For a yes or no question: the probability at or above which the answer counts as yes. Without one the column carries the probability itself and a run draws the line at an even chance."},"range":{"type":"object","properties":{"min":{"type":"integer","description":"The lowest level of the scale."},"max":{"type":"integer","description":"The highest level of the scale."}},"required":["min","max"],"description":"For a rating: the two ends of the scale."},"options":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100,"description":"What the column holds when this option is the answer."},"description":{"type":"string","minLength":1,"maxLength":500,"description":"What this option means, in your own words."}},"required":["name","description"]},"minItems":2,"maxItems":255,"description":"For a choice: the options to pick between."}},"required":["instructions"]},"description":"With target: what to ask of each row. One classification asks them all per row, and the question text is part of what that classification is priced on; the estimate endpoint prices the exact set."},"name":{"type":"string","minLength":1,"maxLength":200,"description":"What to call the run. Yours to choose."},"limit":{"type":"integer","exclusiveMinimum":0,"maximum":100000,"description":"Rows the run may judge. Ten thousand by default on every plan, up to one hundred thousand on a plan that lifts the cap."}}}}}},"security":[{"project_api_key":[]}]},"get":{"operationId":"listInstantEvalRuns","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"runs":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The run id."},"name":{"type":["string","null"],"description":"What the run was called, if anything."},"sql":{"type":"string","description":"The statement, exactly as submitted."},"parameters":{"type":"object","additionalProperties":{"anyOf":[{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"null"}]},{"type":"array","items":{"type":"string"}}]},"description":"The values the statement's parameters were filled with."},"questions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The statement's own output column, which is the name this question is addressed by everywhere else."},"function":{"type":"string","description":"The eval function that asked it."},"kind":{"type":"string","enum":["boolean","score","category"],"description":"What kind of answer the question takes."},"reads":{"type":"string","description":"Which part of the verdict the statement's column carries."},"threshold":{"type":["number","null"],"description":"Where a boolean question's probability becomes a pass. Null for a question that is not a boolean."}},"required":["id","function","kind","reads","threshold"]},"description":"One entry per eval function the statement projects, derived from it when the run was accepted."},"limit":{"type":"integer","description":"Rows this run may judge."},"status":{"type":"string","enum":["queued","planning","running","finished","failed","cancelled"],"description":"Where the run is in its life."},"total":{"type":["integer","null"],"description":"Rows the run found, bounded by its limit. Null until it has looked."},"progress":{"type":"integer","description":"Rows judged so far."},"matched":{"type":["integer","null"],"description":"Judgements that matched, across this run's boolean questions. Null when the run asked none: a score or a category question has no match to count."},"matchedByQuestion":{"type":"object","additionalProperties":{"type":"number"},"description":"Per question: matches for a boolean question, judged rows for a score or a category one."},"failed":{"type":"integer","description":"Rows the judge could not answer."},"skipped":{"type":"integer","description":"Rows the judge declined to answer."},"tokens":{"type":"integer","description":"Input tokens the judge billed for."},"priceUsd":{"type":"number","description":"What the judging costs you, in United States dollars."},"error":{"type":["string","null"],"description":"The code of the failure that ended the run, when one did."},"createdAt":{"type":"string","description":"When the run was accepted."},"updatedAt":{"type":"string","description":"When the run was last written to."},"startedAt":{"type":["string","null"],"description":"When the run began reading rows."},"finishedAt":{"type":["string","null"],"description":"When the run ended."}},"required":["id","name","sql","parameters","questions","limit","status","total","progress","matched","matchedByQuestion","failed","skipped","tokens","priceUsd","error","createdAt","updatedAt","startedAt","finishedAt"]},"description":"The project's runs, newest first."}},"required":["runs"]}}}}},"description":"List the project's runs, newest first. The project comes from the credential, so a run of another project is never listed. Page through them with before, which takes the created time of the oldest run the previous page carried.","tags":["Instant Evals"],"parameters":[{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"description":"Runs to list, at most one hundred."},{"in":"query","name":"before","schema":{"type":"string","format":"date-time"},"description":"List runs accepted strictly before this instant, as an ISO 8601 timestamp. Half of the list's cursor: pass `beforeId` with it."},{"in":"query","name":"beforeId","schema":{"type":"string","minLength":1,"maxLength":200},"description":"The id of the last run of the previous page. Two runs can share an instant, so this is what keeps a page from skipping the others written in the same millisecond."}],"security":[{"project_api_key":[]}]}},"/api/v1/instant-evals/estimate":{"post":{"operationId":"estimateInstantEvalRun","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"rows":{"type":"integer","description":"Rows the statement matches, bounded by the run's limit."},"isRowsCapped":{"type":"boolean","description":"Whether the statement matches more rows than the run may judge."},"avgTokens":{"type":"integer","description":"Input tokens one judged row sends, measured from a sample."},"totalTokens":{"type":"integer","description":"Input tokens the whole run would send."},"requests":{"type":"integer","description":"Classifications the run would make, one per judged row."},"priceUsd":{"type":"number","description":"What the run would cost you, in United States dollars."},"freeBudgetRemainingUsd":{"type":"number","description":"What is left of the free Instant Evals budget, in United States dollars. Only present for an organization without a paid plan."}},"required":["rows","isRowsCapped","avgTokens","totalTokens","requests","priceUsd"]}}}}},"description":"Price a run without starting it. The rows are counted, a sample of their texts is measured, and the cost is worked out from that. Nothing is judged and nothing is charged. Takes the same body a run does, a statement or a target with questions.","summary":"Estimate a run","tags":["Instant Evals"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sql":{"type":"string","minLength":1,"maxLength":50000,"description":"The LangWatchQL statement to judge. It must project TraceId and at least one eval function column. Send this or target, never both."},"parameters":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"null"}]},"description":"Values for the parameters the statement declares."},"target":{"type":"string","enum":["traces","threads","llm_spans"],"description":"What one judged row is, in place of a statement: a trace, a conversation, or one model call. The statement is written for you from this and the questions, and handed back on the run so you can edit it and resubmit."},"filter":{"type":"string","maxLength":4000,"description":"With target: a trace filter, in the language the trace explorer's search bar speaks, narrowing which rows are judged."},"start":{"type":"string","format":"date-time","description":"With target: the oldest instant to judge, as an ISO 8601 timestamp. Defaults to seven days ago."},"end":{"type":"string","format":"date-time","description":"With target: the newest instant to judge. Defaults to now."},"questions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64,"description":"What to call this question. It becomes the statement's output column and the name every judgement is filed under. Defaults to q1, q2 and so on."},"kind":{"type":"string","enum":["boolean","score","category"],"default":"boolean","description":"What kind of answer you want: a yes or no, a rating on a scale, or one of a list of options."},"instructions":{"type":"string","minLength":1,"maxLength":2000,"description":"The question, in your own words, as you would write it for a human reader."},"criteria":{"type":"array","items":{"type":"string","minLength":1,"maxLength":500},"minItems":2,"maxItems":2,"description":"For a yes or no question: what counts as yes, then what counts as no. Cannot be combined with a threshold."},"threshold":{"type":"number","minimum":0,"maximum":1,"description":"For a yes or no question: the probability at or above which the answer counts as yes. Without one the column carries the probability itself and a run draws the line at an even chance."},"range":{"type":"object","properties":{"min":{"type":"integer","description":"The lowest level of the scale."},"max":{"type":"integer","description":"The highest level of the scale."}},"required":["min","max"],"description":"For a rating: the two ends of the scale."},"options":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100,"description":"What the column holds when this option is the answer."},"description":{"type":"string","minLength":1,"maxLength":500,"description":"What this option means, in your own words."}},"required":["name","description"]},"minItems":2,"maxItems":255,"description":"For a choice: the options to pick between."}},"required":["instructions"]},"description":"With target: what to ask of each row. One classification asks them all per row, and the question text is part of what that classification is priced on; the estimate endpoint prices the exact set."},"name":{"type":"string","minLength":1,"maxLength":200,"description":"What to call the run. Yours to choose."},"limit":{"type":"integer","exclusiveMinimum":0,"maximum":100000,"description":"Rows the run may judge. Ten thousand by default on every plan, up to one hundred thousand on a plan that lifts the cap."}}}}}},"security":[{"project_api_key":[]}]}},"/api/v1/instant-evals/{id}":{"get":{"operationId":"getInstantEvalRun","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"The run id."},"name":{"type":["string","null"],"description":"What the run was called, if anything."},"sql":{"type":"string","description":"The statement, exactly as submitted."},"parameters":{"type":"object","additionalProperties":{"anyOf":[{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"null"}]},{"type":"array","items":{"type":"string"}}]},"description":"The values the statement's parameters were filled with."},"questions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The statement's own output column, which is the name this question is addressed by everywhere else."},"function":{"type":"string","description":"The eval function that asked it."},"kind":{"type":"string","enum":["boolean","score","category"],"description":"What kind of answer the question takes."},"reads":{"type":"string","description":"Which part of the verdict the statement's column carries."},"threshold":{"type":["number","null"],"description":"Where a boolean question's probability becomes a pass. Null for a question that is not a boolean."}},"required":["id","function","kind","reads","threshold"]},"description":"One entry per eval function the statement projects, derived from it when the run was accepted."},"limit":{"type":"integer","description":"Rows this run may judge."},"status":{"type":"string","enum":["queued","planning","running","finished","failed","cancelled"],"description":"Where the run is in its life."},"total":{"type":["integer","null"],"description":"Rows the run found, bounded by its limit. Null until it has looked."},"progress":{"type":"integer","description":"Rows judged so far."},"matched":{"type":["integer","null"],"description":"Judgements that matched, across this run's boolean questions. Null when the run asked none: a score or a category question has no match to count."},"matchedByQuestion":{"type":"object","additionalProperties":{"type":"number"},"description":"Per question: matches for a boolean question, judged rows for a score or a category one."},"failed":{"type":"integer","description":"Rows the judge could not answer."},"skipped":{"type":"integer","description":"Rows the judge declined to answer."},"tokens":{"type":"integer","description":"Input tokens the judge billed for."},"priceUsd":{"type":"number","description":"What the judging costs you, in United States dollars."},"error":{"type":["string","null"],"description":"The code of the failure that ended the run, when one did."},"createdAt":{"type":"string","description":"When the run was accepted."},"updatedAt":{"type":"string","description":"When the run was last written to."},"startedAt":{"type":["string","null"],"description":"When the run began reading rows."},"finishedAt":{"type":["string","null"],"description":"When the run ended."}},"required":["id","name","sql","parameters","questions","limit","status","total","progress","matched","matchedByQuestion","failed","skipped","tokens","priceUsd","error","createdAt","updatedAt","startedAt","finishedAt"]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"description":"Read one run: its status, how many rows it found and judged, how many matched in total and per question, what it could not answer, and the tokens, cost and price the judging came to. An id this project does not hold answers 404 instant_eval_not_found.","tags":["Instant Evals"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1},"required":true,"description":"The run id."}],"security":[{"project_api_key":[]}]}},"/api/v1/instant-evals/{id}/cancel":{"post":{"operationId":"cancelInstantEvalRun","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"The run id."},"name":{"type":["string","null"],"description":"What the run was called, if anything."},"sql":{"type":"string","description":"The statement, exactly as submitted."},"parameters":{"type":"object","additionalProperties":{"anyOf":[{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"null"}]},{"type":"array","items":{"type":"string"}}]},"description":"The values the statement's parameters were filled with."},"questions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The statement's own output column, which is the name this question is addressed by everywhere else."},"function":{"type":"string","description":"The eval function that asked it."},"kind":{"type":"string","enum":["boolean","score","category"],"description":"What kind of answer the question takes."},"reads":{"type":"string","description":"Which part of the verdict the statement's column carries."},"threshold":{"type":["number","null"],"description":"Where a boolean question's probability becomes a pass. Null for a question that is not a boolean."}},"required":["id","function","kind","reads","threshold"]},"description":"One entry per eval function the statement projects, derived from it when the run was accepted."},"limit":{"type":"integer","description":"Rows this run may judge."},"status":{"type":"string","enum":["queued","planning","running","finished","failed","cancelled"],"description":"Where the run is in its life."},"total":{"type":["integer","null"],"description":"Rows the run found, bounded by its limit. Null until it has looked."},"progress":{"type":"integer","description":"Rows judged so far."},"matched":{"type":["integer","null"],"description":"Judgements that matched, across this run's boolean questions. Null when the run asked none: a score or a category question has no match to count."},"matchedByQuestion":{"type":"object","additionalProperties":{"type":"number"},"description":"Per question: matches for a boolean question, judged rows for a score or a category one."},"failed":{"type":"integer","description":"Rows the judge could not answer."},"skipped":{"type":"integer","description":"Rows the judge declined to answer."},"tokens":{"type":"integer","description":"Input tokens the judge billed for."},"priceUsd":{"type":"number","description":"What the judging costs you, in United States dollars."},"error":{"type":["string","null"],"description":"The code of the failure that ended the run, when one did."},"createdAt":{"type":"string","description":"When the run was accepted."},"updatedAt":{"type":"string","description":"When the run was last written to."},"startedAt":{"type":["string","null"],"description":"When the run began reading rows."},"finishedAt":{"type":["string","null"],"description":"When the run ended."}},"required":["id","name","sql","parameters","questions","limit","status","total","progress","matched","matchedByQuestion","failed","skipped","tokens","priceUsd","error","createdAt","updatedAt","startedAt","finishedAt"]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"description":"Ask a run to stop. The run stops before its next page, so the pages it already judged keep their judgements and are still readable. A run that has already finished, failed or been cancelled answers 409 instant_eval_already_finished.","summary":"Cancel a run","tags":["Instant Evals"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1},"required":true,"description":"The run id."}],"security":[{"project_api_key":[]}]}},"/api/v1/instant-evals/{id}/results":{"get":{"operationId":"listInstantEvalRunResults","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"judgments":{"type":"array","items":{"type":"object","properties":{"traceId":{"type":"string","description":"The trace the judgement is about."},"questionId":{"type":"string","description":"The question it answers, named by its output column."},"threadId":{"type":"string","description":"The conversation the trace belongs to."},"spanId":{"type":"string","description":"The span the judged text was read from."},"kind":{"type":"string","description":"What kind of question was asked."},"status":{"type":"string","enum":["judged","skipped","failed"],"description":"Whether the judge answered, declined, or could not answer."},"passed":{"type":["boolean","null"],"description":"Whether a boolean question passed its threshold."},"score":{"type":["number","null"],"description":"A score question's answer."},"label":{"type":["string","null"],"description":"A category question's answer."},"probability":{"type":["number","null"],"description":"How likely the judge found a boolean question's answer to be true."},"probabilities":{"type":["object","null"],"additionalProperties":{"type":"number"},"description":"The full distribution behind a category answer."},"error":{"type":["string","null"],"description":"Why the judge could not answer, when it could not."},"occurredAt":{"type":"string","description":"When the judgement was made."}},"required":["traceId","questionId","threadId","spanId","kind","status","passed","score","label","probability","probabilities","error","occurredAt"]},"description":"One page of the run's judgements."},"nextCursor":{"type":"string","description":"Pass as cursor to read the page after this one. Absent on the last page."}},"required":["judgments"]}}}}},"description":"Read the run's judgements, one page at a time. Pass the cursor a page answers with to read the page after it; the last page carries no cursor, and no judgement is ever carried by two pages. Narrow the page with questionId, matched and status.","summary":"Read a run's results","tags":["Instant Evals"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1},"required":true,"description":"The run id."},{"in":"query","name":"questionId","schema":{"type":"string","minLength":1},"description":"Only this question's judgements."},{"in":"query","name":"matched","schema":{"type":"string","enum":["true","1","yes","false","0","no"]},"description":"Only judgements that matched, or only those that did not. Omit for both."},{"in":"query","name":"status","schema":{"type":"string","enum":["judged","skipped","failed"]},"description":"Only judgements in this state."},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":1000,"default":100},"description":"Judgements per page, at most one thousand."},{"in":"query","name":"cursor","schema":{"type":"string","minLength":1,"maxLength":500},"description":"The cursor the previous page answered with."}],"security":[{"project_api_key":[]}]}},"/api/v1/instant-evals/{id}/sample":{"get":{"operationId":"sampleInstantEvalRun","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"rows":{"type":"array","items":{"type":"object","additionalProperties":{}},"description":"The statement's own rows, with each judged column holding the text that was judged rather than the verdict."},"judgments":{"type":"array","items":{"type":"object","properties":{"traceId":{"type":"string","description":"The trace the judgement is about."},"questionId":{"type":"string","description":"The question it answers, named by its output column."},"threadId":{"type":"string","description":"The conversation the trace belongs to."},"spanId":{"type":"string","description":"The span the judged text was read from."},"kind":{"type":"string","description":"What kind of question was asked."},"status":{"type":"string","enum":["judged","skipped","failed"],"description":"Whether the judge answered, declined, or could not answer."},"passed":{"type":["boolean","null"],"description":"Whether a boolean question passed its threshold."},"score":{"type":["number","null"],"description":"A score question's answer."},"label":{"type":["string","null"],"description":"A category question's answer."},"probability":{"type":["number","null"],"description":"How likely the judge found a boolean question's answer to be true."},"probabilities":{"type":["object","null"],"additionalProperties":{"type":"number"},"description":"The full distribution behind a category answer."},"error":{"type":["string","null"],"description":"Why the judge could not answer, when it could not."},"occurredAt":{"type":"string","description":"When the judgement was made."}},"required":["traceId","questionId","threadId","spanId","kind","status","passed","score","label","probability","probabilities","error","occurredAt"]},"description":"The verdicts those rows received."}},"required":["rows","judgments"]}}}}},"description":"Read a few of the run's rows with the text that was judged beside the verdict it received. The text is re-read through the statement's own extraction functions, so nothing is judged again and reading a sample is free.","summary":"Sample a run","tags":["Instant Evals"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1},"required":true,"description":"The run id."},{"in":"query","name":"n","schema":{"type":"integer","minimum":1,"maximum":25,"default":5},"description":"Rows to re-read, at most twenty five."}],"security":[{"project_api_key":[]}]}},"/api/v1/run-plans":{"get":{"operationId":"listRunPlans","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The run plan id."},"name":{"type":"string","description":"The run plan name. This is the plan's identity: a run started under this name joins this plan."},"slug":{"type":"string","description":"The plan's address in the platform. It is kept when the plan is renamed, so run history never moves."},"scope":{"oneOf":[{"type":"object","properties":{"mode":{"type":"string","const":"all"}},"required":["mode"]},{"type":"object","properties":{"mode":{"type":"string","const":"test_suites"},"testSuiteIds":{"type":"array","items":{"type":"string"}}},"required":["mode","testSuiteIds"]},{"type":"object","properties":{"mode":{"type":"string","const":"labels"},"labels":{"type":"array","items":{"type":"string"}}},"required":["mode","labels"]},{"type":"object","properties":{"mode":{"type":"string","const":"scenarios"}},"required":["mode"]}],"description":"What the run plan covers: all (every active scenario), test_suites (the scenarios filed in the named test suites), labels (the scenarios carrying any of the labels), or scenarios (the scenarioIds sent with the configuration). A dynamic scope is resolved again at every run, so a scenario written later runs without editing the plan."},"scenarioIds":{"type":"array","items":{"type":"string"},"description":"The scenarios the last run of this plan covered."},"targets":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["prompt","http","code","workflow","connected","voice"],"description":"What kind of thing the scenarios run against. A connected agent is one registered from code with the SDK."},"referenceId":{"type":"string","description":"The id of the prompt, agent or workflow to run against. A connected target may also say <name>@<environment>, for example support-agent@production, which resolves to the agent id."},"runParameters":{"type":"object","additionalProperties":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"description":"Parameter values this target alone runs with, by name. They are merged over the run-level parameters and the target wins, so two targets may name the same agent with different values: that is how one run compares one agent on two models, and the results show one column for each target."}},"required":["type","referenceId"]},"description":"What the plan runs against, in the order the results show. A target carrying runParameters runs with those values."},"repeatCount":{"type":"number","description":"How many times each scenario and target pairing runs."},"simulatorModel":{"type":["string","null"],"description":"The model that plays the user, or null for the scenario or project default."},"judgeModel":{"type":["string","null"],"description":"The model that judges the run, or null for the scenario or project default."},"labels":{"type":"array","items":{"type":"string"},"description":"The labels the plan carries."},"evaluators":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"evaluatorId":{"type":"string","minLength":1},"required":{"type":"boolean"},"mappings":{"type":"object","propertyNames":{"type":"string","minLength":1,"maxLength":128},"additionalProperties":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"source"},"sourceId":{"type":"string","enum":["conversation","scenario","trace"]},"path":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"minItems":1,"maxItems":3}},"required":["type","sourceId","path"]},{"type":"object","properties":{"type":{"type":"string","const":"value"},"value":{"type":"string","maxLength":65536}},"required":["type","value"]}]},"description":"Where each evaluator input reads its value, keyed by input name. Inputs left out are unmapped; a required input left unmapped refuses the run."}},"required":["id","evaluatorId","required","mappings"],"description":"One evaluator that runs after every scenario run, with where each of its inputs reads from."},"maxItems":20,"description":"The plan's own evaluators. Absent on servers that predate evaluators on this family."},"archivedAt":{"type":["string","null"],"description":"When the plan was archived, or null while it is active."},"createdAt":{"type":"string","description":"When the plan was created."},"updatedAt":{"type":"string","description":"When the plan was last written."},"platformUrl":{"type":"string","format":"uri","description":"Where to open this run plan in the LangWatch platform."}},"required":["id","name","slug","scope","scenarioIds","targets","repeatCount","simulatorModel","judgeModel","labels","archivedAt","createdAt","updatedAt","platformUrl"]}}}}}},"description":"List the project's run plans. Archived plans are left out unless includeArchived is set. Test suites are not run plans and are listed by the test suites family.","tags":["Run Plans"],"parameters":[{"in":"query","name":"includeArchived","schema":{"type":"string","default":"false"},"description":"Include archived run plans in the list. true, 1, yes for yes; false, 0, no or omitted for no."}],"security":[{"project_api_key":[]}]}},"/api/v1/run-plans/run":{"post":{"operationId":"runRunPlan","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"scheduled":{"type":"boolean","description":"True once the runs are queued."},"batchRunId":{"type":"string","description":"The id of this batch. Every run started here carries it."},"setId":{"type":"string","description":"The result set the batch is filed under in the platform."},"jobCount":{"type":"number","description":"How many runs were queued."},"skippedArchived":{"type":"object","properties":{"scenarios":{"type":"array","items":{"type":"string"},"description":"Scenarios left out because they are archived."},"targets":{"type":"array","items":{"type":"string"},"description":"Targets left out because they are archived."}},"required":["scenarios","targets"],"description":"What the run left out, and why."},"items":{"type":"array","items":{"type":"object","properties":{"scenarioRunId":{"type":"string","description":"The id of this single run."},"scenarioId":{"type":"string","description":"The scenario that was run."},"target":{"type":"object","properties":{"type":{"type":"string","enum":["prompt","http","code","workflow","connected","voice"],"description":"What kind of thing the scenarios run against. A connected agent is one registered from code with the SDK."},"referenceId":{"type":"string","description":"The id of the prompt, agent or workflow to run against. A connected target may also say <name>@<environment>, for example support-agent@production, which resolves to the agent id."},"runParameters":{"type":"object","additionalProperties":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"description":"Parameter values this target alone runs with, by name. They are merged over the run-level parameters and the target wins, so two targets may name the same agent with different values: that is how one run compares one agent on two models, and the results show one column for each target."}},"required":["type","referenceId"],"description":"What it was run against."},"name":{"type":["string","null"],"description":"The scenario name, when known."}},"required":["scenarioRunId","scenarioId","target","name"]},"description":"Every run this call queued."},"runPlanId":{"type":"string","description":"The run plan this run was filed under."},"planName":{"type":"string","description":"The name that plan answers to."},"created":{"type":"boolean","description":"True when this run created the plan, false when it joined a plan already there."},"platformUrl":{"type":"string","format":"uri","description":"Where to watch this run in the LangWatch platform."}},"required":["scheduled","batchRunId","setId","jobCount","skippedArchived","items","runPlanId","planName","created","platformUrl"]}}}}},"description":"Run a configuration under a name. The name identifies the run plan: send a name already in use and that plan's configuration is replaced with this one, send a new name and the plan is created, send no name and one is derived from what the run covers and what it runs against.","tags":["Run Plans"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200,"description":"The run plan this run joins or creates. A run plan is identified by its name, so sending the same name again replaces that plan's configuration with this one. Leave it out and the name is derived from what the run covers and what it runs against. Up to 200 characters."},"config":{"type":"object","properties":{"scope":{"oneOf":[{"type":"object","properties":{"mode":{"type":"string","const":"all"}},"required":["mode"]},{"type":"object","properties":{"mode":{"type":"string","const":"test_suites"},"testSuiteIds":{"type":"array","items":{"type":"string"}}},"required":["mode","testSuiteIds"]},{"type":"object","properties":{"mode":{"type":"string","const":"labels"},"labels":{"type":"array","items":{"type":"string"}}},"required":["mode","labels"]},{"type":"object","properties":{"mode":{"type":"string","const":"scenarios"}},"required":["mode"]}],"description":"What the run plan covers: all (every active scenario), test_suites (the scenarios filed in the named test suites), labels (the scenarios carrying any of the labels), or scenarios (the scenarioIds sent with the configuration). A dynamic scope is resolved again at every run, so a scenario written later runs without editing the plan."},"targets":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["prompt","http","code","workflow","connected","voice"],"description":"What kind of thing the scenarios run against. A connected agent is one registered from code with the SDK."},"referenceId":{"type":"string","description":"The id of the prompt, agent or workflow to run against. A connected target may also say <name>@<environment>, for example support-agent@production, which resolves to the agent id."},"runParameters":{"type":"object","additionalProperties":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"description":"Parameter values this target alone runs with, by name. They are merged over the run-level parameters and the target wins, so two targets may name the same agent with different values: that is how one run compares one agent on two models, and the results show one column for each target."}},"required":["type","referenceId"]},"description":"The prompts, agents or workflows every scenario runs against. Every target runs every scenario, so naming more than one compares them in the same run."},"repeatCount":{"type":"integer","minimum":1,"maximum":5,"description":"How many times each scenario and target pairing runs. Between 1 and 5; defaults to 1."},"simulatorModel":{"type":["string","null"],"pattern":"^[a-zA-Z0-9_-]+(?:\\/[^\\s/]+)+$","maxLength":200,"description":"The model that plays the user for every scenario in the run. Overrides each scenario's own choice. Leave it out for the scenario or project default."},"judgeModel":{"type":["string","null"],"pattern":"^[a-zA-Z0-9_-]+(?:\\/[^\\s/]+)+$","maxLength":200,"description":"The model that judges every scenario in the run. Overrides each scenario's own choice. Leave it out for the scenario or project default."},"scenarioIds":{"type":"array","items":{"type":"string"},"description":"The scenarios a test_suites or scenarios scope covers. Read by a scenarios scope alone; a scope that states a rule resolves its own list at run time."},"evaluators":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"evaluatorId":{"type":"string","minLength":1},"required":{"type":"boolean"},"mappings":{"type":"object","propertyNames":{"type":"string","minLength":1,"maxLength":128},"additionalProperties":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"source"},"sourceId":{"type":"string","enum":["conversation","scenario","trace"]},"path":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"minItems":1,"maxItems":3}},"required":["type","sourceId","path"]},{"type":"object","properties":{"type":{"type":"string","const":"value"},"value":{"type":"string","maxLength":65536}},"required":["type","value"]}]},"description":"Where each evaluator input reads its value, keyed by input name. Inputs left out are unmapped; a required input left unmapped refuses the run."}},"required":["id","evaluatorId","required","mappings"],"description":"One evaluator that runs after every scenario run, with where each of its inputs reads from."},"maxItems":20,"description":"The plan's own evaluators, run beside the ones attached to the test suites its scenarios belong to. A plan evaluator reads the conversation and the trace, never a scenario field. Leave it out to keep what the plan already holds."}},"required":["scope","targets"],"description":"What this run covers and what it runs against. Written onto the run plan the name resolves."},"idempotencyKey":{"type":"string","description":"Repeat the same key to make a retry join the batch the first call started instead of running everything again. Defaults to a new key per call."},"parameters":{"type":"object","additionalProperties":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"description":"Constant values applied to every scenario in the run, e.g. a fixture id or a tenant. A value supplied here overrides the scenario's own default for that name, and a target that names the same parameter in its runParameters overrides it for that target."},"note":{"type":"string","maxLength":200,"description":"One short line describing why this batch was run, e.g. a commit hash or what you changed. It is stored on every run of the batch and shown beside the run in the platform. Up to 200 characters."}},"required":["config"]}}}},"security":[{"project_api_key":[]}]}},"/api/v1/run-plans/{id}":{"get":{"operationId":"getRunPlan","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"The run plan id."},"name":{"type":"string","description":"The run plan name. This is the plan's identity: a run started under this name joins this plan."},"slug":{"type":"string","description":"The plan's address in the platform. It is kept when the plan is renamed, so run history never moves."},"scope":{"oneOf":[{"type":"object","properties":{"mode":{"type":"string","const":"all"}},"required":["mode"]},{"type":"object","properties":{"mode":{"type":"string","const":"test_suites"},"testSuiteIds":{"type":"array","items":{"type":"string"}}},"required":["mode","testSuiteIds"]},{"type":"object","properties":{"mode":{"type":"string","const":"labels"},"labels":{"type":"array","items":{"type":"string"}}},"required":["mode","labels"]},{"type":"object","properties":{"mode":{"type":"string","const":"scenarios"}},"required":["mode"]}],"description":"What the run plan covers: all (every active scenario), test_suites (the scenarios filed in the named test suites), labels (the scenarios carrying any of the labels), or scenarios (the scenarioIds sent with the configuration). A dynamic scope is resolved again at every run, so a scenario written later runs without editing the plan."},"scenarioIds":{"type":"array","items":{"type":"string"},"description":"The scenarios the last run of this plan covered."},"targets":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["prompt","http","code","workflow","connected","voice"],"description":"What kind of thing the scenarios run against. A connected agent is one registered from code with the SDK."},"referenceId":{"type":"string","description":"The id of the prompt, agent or workflow to run against. A connected target may also say <name>@<environment>, for example support-agent@production, which resolves to the agent id."},"runParameters":{"type":"object","additionalProperties":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"description":"Parameter values this target alone runs with, by name. They are merged over the run-level parameters and the target wins, so two targets may name the same agent with different values: that is how one run compares one agent on two models, and the results show one column for each target."}},"required":["type","referenceId"]},"description":"What the plan runs against, in the order the results show. A target carrying runParameters runs with those values."},"repeatCount":{"type":"number","description":"How many times each scenario and target pairing runs."},"simulatorModel":{"type":["string","null"],"description":"The model that plays the user, or null for the scenario or project default."},"judgeModel":{"type":["string","null"],"description":"The model that judges the run, or null for the scenario or project default."},"labels":{"type":"array","items":{"type":"string"},"description":"The labels the plan carries."},"evaluators":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"evaluatorId":{"type":"string","minLength":1},"required":{"type":"boolean"},"mappings":{"type":"object","propertyNames":{"type":"string","minLength":1,"maxLength":128},"additionalProperties":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"source"},"sourceId":{"type":"string","enum":["conversation","scenario","trace"]},"path":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"minItems":1,"maxItems":3}},"required":["type","sourceId","path"]},{"type":"object","properties":{"type":{"type":"string","const":"value"},"value":{"type":"string","maxLength":65536}},"required":["type","value"]}]},"description":"Where each evaluator input reads its value, keyed by input name. Inputs left out are unmapped; a required input left unmapped refuses the run."}},"required":["id","evaluatorId","required","mappings"],"description":"One evaluator that runs after every scenario run, with where each of its inputs reads from."},"maxItems":20,"description":"The plan's own evaluators. Absent on servers that predate evaluators on this family."},"archivedAt":{"type":["string","null"],"description":"When the plan was archived, or null while it is active."},"createdAt":{"type":"string","description":"When the plan was created."},"updatedAt":{"type":"string","description":"When the plan was last written."},"platformUrl":{"type":"string","format":"uri","description":"Where to open this run plan in the LangWatch platform."}},"required":["id","name","slug","scope","scenarioIds","targets","repeatCount","simulatorModel","judgeModel","labels","archivedAt","createdAt","updatedAt","platformUrl"]}}}}},"description":"Read one run plan. An id the project does not hold, and a test suite id, both answer 404 suite_not_found.","tags":["Run Plans"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1},"required":true,"description":"The run plan id."}],"security":[{"project_api_key":[]}]},"delete":{"operationId":"archiveRunPlan","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"The run plan that was archived."},"archived":{"type":"boolean","const":true,"description":"Always true once the plan is archived."}},"required":["id","archived"]}}}}},"description":"Archive a run plan. The plan stops being listed and its run history is kept. The scenarios it referenced are left where they are.","tags":["Run Plans"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1},"required":true,"description":"The run plan id."}],"security":[{"project_api_key":[]}]}},"/api/v1/run-plans/{id}/run":{"post":{"operationId":"rerunRunPlan","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"scheduled":{"type":"boolean","description":"True once the runs are queued."},"batchRunId":{"type":"string","description":"The id of this batch. Every run started here carries it."},"setId":{"type":"string","description":"The result set the batch is filed under in the platform."},"jobCount":{"type":"number","description":"How many runs were queued."},"skippedArchived":{"type":"object","properties":{"scenarios":{"type":"array","items":{"type":"string"},"description":"Scenarios left out because they are archived."},"targets":{"type":"array","items":{"type":"string"},"description":"Targets left out because they are archived."}},"required":["scenarios","targets"],"description":"What the run left out, and why."},"items":{"type":"array","items":{"type":"object","properties":{"scenarioRunId":{"type":"string","description":"The id of this single run."},"scenarioId":{"type":"string","description":"The scenario that was run."},"target":{"type":"object","properties":{"type":{"type":"string","enum":["prompt","http","code","workflow","connected","voice"],"description":"What kind of thing the scenarios run against. A connected agent is one registered from code with the SDK."},"referenceId":{"type":"string","description":"The id of the prompt, agent or workflow to run against. A connected target may also say <name>@<environment>, for example support-agent@production, which resolves to the agent id."},"runParameters":{"type":"object","additionalProperties":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"description":"Parameter values this target alone runs with, by name. They are merged over the run-level parameters and the target wins, so two targets may name the same agent with different values: that is how one run compares one agent on two models, and the results show one column for each target."}},"required":["type","referenceId"],"description":"What it was run against."},"name":{"type":["string","null"],"description":"The scenario name, when known."}},"required":["scenarioRunId","scenarioId","target","name"]},"description":"Every run this call queued."},"runPlanId":{"type":"string","description":"The run plan this run was filed under."},"planName":{"type":"string","description":"The name that plan answers to."},"created":{"type":"boolean","description":"True when this run created the plan, false when it joined a plan already there."},"platformUrl":{"type":"string","format":"uri","description":"Where to watch this run in the LangWatch platform."}},"required":["scheduled","batchRunId","setId","jobCount","skippedArchived","items","runPlanId","planName","created","platformUrl"]}}}}},"description":"Run a run plan again, with the configuration it already holds. To run a different configuration, post it to /run under the plan's name.","summary":"Run a plan again","tags":["Run Plans"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1},"required":true,"description":"The run plan id."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"idempotencyKey":{"type":"string","description":"Repeat the same key to make a retry join the batch the first call started instead of running everything again. Defaults to a new key per call."},"parameters":{"type":"object","additionalProperties":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"description":"Constant values applied to every scenario in the run, e.g. a fixture id or a tenant. A value supplied here overrides the scenario's own default for that name, and a target that names the same parameter in its runParameters overrides it for that target."},"note":{"type":"string","maxLength":200,"description":"One short line describing why this batch was run, e.g. a commit hash or what you changed. It is stored on every run of the batch and shown beside the run in the platform. Up to 200 characters."}}}}}},"security":[{"project_api_key":[]}]}},"/api/v1/test-suites":{"get":{"operationId":"listTestSuites","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The test suite id."},"name":{"type":"string","description":"The test suite name."},"slug":{"type":"string","description":"The suite's address in the platform. It is kept when the suite is renamed."},"scenarioIds":{"type":"array","items":{"type":"string"},"description":"The scenarios filed in this suite, in the order it shows them."},"scenarioCount":{"type":"number","description":"How many scenarios are filed in it."},"fields":{"type":"array","items":{"type":"object","properties":{"identifier":{"type":"string","pattern":"^[a-z][a-z0-9_]*$","minLength":1,"maxLength":64},"type":{"type":"string","enum":["text","number","boolean"]}},"required":["identifier","type"]},"maxItems":30,"description":"The fields the test suite declares. Absent on servers that predate fields on this family."},"evaluators":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"evaluatorId":{"type":"string","minLength":1},"required":{"type":"boolean"},"mappings":{"type":"object","propertyNames":{"type":"string","minLength":1,"maxLength":128},"additionalProperties":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"source"},"sourceId":{"type":"string","enum":["conversation","scenario","trace"]},"path":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"minItems":1,"maxItems":3}},"required":["type","sourceId","path"]},{"type":"object","properties":{"type":{"type":"string","const":"value"},"value":{"type":"string","maxLength":65536}},"required":["type","value"]}]},"description":"Where each evaluator input reads its value, keyed by input name. Inputs left out are unmapped; a required input left unmapped refuses the run."}},"required":["id","evaluatorId","required","mappings"],"description":"One evaluator that runs after every scenario run, with where each of its inputs reads from."},"maxItems":20,"description":"The evaluators attached to the test suite. Absent on servers that predate evaluators on this family."},"archivedAt":{"type":["string","null"],"description":"When the suite was archived, or null while it is active."},"createdAt":{"type":"string","description":"When the suite was created."},"updatedAt":{"type":"string","description":"When the suite was last written."},"platformUrl":{"type":"string","format":"uri","description":"Where to open this test suite in the LangWatch platform."}},"required":["id","name","slug","scenarioIds","scenarioCount","archivedAt","createdAt","updatedAt","platformUrl"]}}}}}},"description":"List the project's test suites. Archived suites are left out unless includeArchived is set. Run plans are not test suites and are listed by the run plans family.","tags":["Test Suites"],"parameters":[{"in":"query","name":"includeArchived","schema":{"type":"string","default":"false"},"description":"Include archived test suites in the list. true, 1, yes for yes; false, 0, no or omitted for no."}],"security":[{"project_api_key":[]}]},"post":{"operationId":"createTestSuite","responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"The test suite id."},"name":{"type":"string","description":"The test suite name."},"slug":{"type":"string","description":"The suite's address in the platform. It is kept when the suite is renamed."},"scenarioIds":{"type":"array","items":{"type":"string"},"description":"The scenarios filed in this suite, in the order it shows them."},"scenarioCount":{"type":"number","description":"How many scenarios are filed in it."},"fields":{"type":"array","items":{"type":"object","properties":{"identifier":{"type":"string","pattern":"^[a-z][a-z0-9_]*$","minLength":1,"maxLength":64},"type":{"type":"string","enum":["text","number","boolean"]}},"required":["identifier","type"]},"maxItems":30,"description":"The fields the test suite declares. Absent on servers that predate fields on this family."},"evaluators":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"evaluatorId":{"type":"string","minLength":1},"required":{"type":"boolean"},"mappings":{"type":"object","propertyNames":{"type":"string","minLength":1,"maxLength":128},"additionalProperties":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"source"},"sourceId":{"type":"string","enum":["conversation","scenario","trace"]},"path":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"minItems":1,"maxItems":3}},"required":["type","sourceId","path"]},{"type":"object","properties":{"type":{"type":"string","const":"value"},"value":{"type":"string","maxLength":65536}},"required":["type","value"]}]},"description":"Where each evaluator input reads its value, keyed by input name. Inputs left out are unmapped; a required input left unmapped refuses the run."}},"required":["id","evaluatorId","required","mappings"],"description":"One evaluator that runs after every scenario run, with where each of its inputs reads from."},"maxItems":20,"description":"The evaluators attached to the test suite. Absent on servers that predate evaluators on this family."},"archivedAt":{"type":["string","null"],"description":"When the suite was archived, or null while it is active."},"createdAt":{"type":"string","description":"When the suite was created."},"updatedAt":{"type":"string","description":"When the suite was last written."},"platformUrl":{"type":"string","format":"uri","description":"Where to open this test suite in the LangWatch platform."}},"required":["id","name","slug","scenarioIds","scenarioCount","archivedAt","createdAt","updatedAt","platformUrl"]}}}}},"description":"Create a test suite. It starts with no scenario: scenarios join it by being filed into it, and the targets a run goes against are sent with the run. It may declare fields and attach evaluators from the start.","tags":["Test Suites"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200,"description":"The test suite name, as it reads in the platform."},"fields":{"type":"array","items":{"type":"object","properties":{"identifier":{"type":"string","pattern":"^[a-z][a-z0-9_]*$","minLength":1,"maxLength":64},"type":{"type":"string","enum":["text","number","boolean"]}},"required":["identifier","type"]},"maxItems":30,"description":"The fields the test suite declares, in the order the platform shows them. Up to 30. An identifier is lowercase letters, digits and underscores, starting with a letter; the type is text, number or boolean."},"evaluators":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"evaluatorId":{"type":"string","minLength":1},"required":{"type":"boolean"},"mappings":{"type":"object","propertyNames":{"type":"string","minLength":1,"maxLength":128},"additionalProperties":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"source"},"sourceId":{"type":"string","enum":["conversation","scenario","trace"]},"path":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"minItems":1,"maxItems":3}},"required":["type","sourceId","path"]},{"type":"object","properties":{"type":{"type":"string","const":"value"},"value":{"type":"string","maxLength":65536}},"required":["type","value"]}]},"description":"Where each evaluator input reads its value, keyed by input name. Inputs left out are unmapped; a required input left unmapped refuses the run."}},"required":["id","evaluatorId","required","mappings"],"description":"One evaluator that runs after every scenario run, with where each of its inputs reads from."},"maxItems":20,"description":"The evaluators that run after every scenario run. Up to 20. A required evaluator that fails fails the scenario; a score-only evaluator reports and never gates."}},"required":["name"]}}}},"security":[{"project_api_key":[]}]}},"/api/v1/test-suites/{id}":{"get":{"operationId":"getTestSuite","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"The test suite id."},"name":{"type":"string","description":"The test suite name."},"slug":{"type":"string","description":"The suite's address in the platform. It is kept when the suite is renamed."},"scenarioIds":{"type":"array","items":{"type":"string"},"description":"The scenarios filed in this suite, in the order it shows them."},"scenarioCount":{"type":"number","description":"How many scenarios are filed in it."},"fields":{"type":"array","items":{"type":"object","properties":{"identifier":{"type":"string","pattern":"^[a-z][a-z0-9_]*$","minLength":1,"maxLength":64},"type":{"type":"string","enum":["text","number","boolean"]}},"required":["identifier","type"]},"maxItems":30,"description":"The fields the test suite declares. Absent on servers that predate fields on this family."},"evaluators":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"evaluatorId":{"type":"string","minLength":1},"required":{"type":"boolean"},"mappings":{"type":"object","propertyNames":{"type":"string","minLength":1,"maxLength":128},"additionalProperties":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"source"},"sourceId":{"type":"string","enum":["conversation","scenario","trace"]},"path":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"minItems":1,"maxItems":3}},"required":["type","sourceId","path"]},{"type":"object","properties":{"type":{"type":"string","const":"value"},"value":{"type":"string","maxLength":65536}},"required":["type","value"]}]},"description":"Where each evaluator input reads its value, keyed by input name. Inputs left out are unmapped; a required input left unmapped refuses the run."}},"required":["id","evaluatorId","required","mappings"],"description":"One evaluator that runs after every scenario run, with where each of its inputs reads from."},"maxItems":20,"description":"The evaluators attached to the test suite. Absent on servers that predate evaluators on this family."},"archivedAt":{"type":["string","null"],"description":"When the suite was archived, or null while it is active."},"createdAt":{"type":"string","description":"When the suite was created."},"updatedAt":{"type":"string","description":"When the suite was last written."},"platformUrl":{"type":"string","format":"uri","description":"Where to open this test suite in the LangWatch platform."},"scenarios":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The scenario id."},"name":{"type":"string","description":"The scenario name."}},"required":["id","name"]},"description":"The active scenarios filed in this suite. An archived scenario is left out."}},"required":["id","name","slug","scenarioIds","scenarioCount","archivedAt","createdAt","updatedAt","platformUrl","scenarios"]}}}}},"description":"Read one test suite with the scenarios filed in it, named. An id the project does not hold, and a run plan id, both answer 404 suite_not_found.","summary":"Read one test suite","tags":["Test Suites"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1},"required":true,"description":"The test suite id."}],"security":[{"project_api_key":[]}]},"patch":{"operationId":"updateTestSuite","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"The test suite id."},"name":{"type":"string","description":"The test suite name."},"slug":{"type":"string","description":"The suite's address in the platform. It is kept when the suite is renamed."},"scenarioIds":{"type":"array","items":{"type":"string"},"description":"The scenarios filed in this suite, in the order it shows them."},"scenarioCount":{"type":"number","description":"How many scenarios are filed in it."},"fields":{"type":"array","items":{"type":"object","properties":{"identifier":{"type":"string","pattern":"^[a-z][a-z0-9_]*$","minLength":1,"maxLength":64},"type":{"type":"string","enum":["text","number","boolean"]}},"required":["identifier","type"]},"maxItems":30,"description":"The fields the test suite declares. Absent on servers that predate fields on this family."},"evaluators":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"evaluatorId":{"type":"string","minLength":1},"required":{"type":"boolean"},"mappings":{"type":"object","propertyNames":{"type":"string","minLength":1,"maxLength":128},"additionalProperties":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"source"},"sourceId":{"type":"string","enum":["conversation","scenario","trace"]},"path":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"minItems":1,"maxItems":3}},"required":["type","sourceId","path"]},{"type":"object","properties":{"type":{"type":"string","const":"value"},"value":{"type":"string","maxLength":65536}},"required":["type","value"]}]},"description":"Where each evaluator input reads its value, keyed by input name. Inputs left out are unmapped; a required input left unmapped refuses the run."}},"required":["id","evaluatorId","required","mappings"],"description":"One evaluator that runs after every scenario run, with where each of its inputs reads from."},"maxItems":20,"description":"The evaluators attached to the test suite. Absent on servers that predate evaluators on this family."},"archivedAt":{"type":["string","null"],"description":"When the suite was archived, or null while it is active."},"createdAt":{"type":"string","description":"When the suite was created."},"updatedAt":{"type":"string","description":"When the suite was last written."},"platformUrl":{"type":"string","format":"uri","description":"Where to open this test suite in the LangWatch platform."}},"required":["id","name","slug","scenarioIds","scenarioCount","archivedAt","createdAt","updatedAt","platformUrl"]}}}}},"description":"Edit a test suite: its name, the fields it declares, the evaluators attached to it. Send only what changes. The slug is kept on a rename, so links and run history stay where they are.","tags":["Test Suites"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1},"required":true,"description":"The test suite id."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200,"description":"The new name. The slug is kept."},"fields":{"type":"array","items":{"type":"object","properties":{"identifier":{"type":"string","pattern":"^[a-z][a-z0-9_]*$","minLength":1,"maxLength":64},"type":{"type":"string","enum":["text","number","boolean"]}},"required":["identifier","type"]},"maxItems":30,"description":"The full list of fields the suite declares. A field an attached evaluator still reads cannot be removed: answers 422 suite_field_in_use."},"evaluators":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"evaluatorId":{"type":"string","minLength":1},"required":{"type":"boolean"},"mappings":{"type":"object","propertyNames":{"type":"string","minLength":1,"maxLength":128},"additionalProperties":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"source"},"sourceId":{"type":"string","enum":["conversation","scenario","trace"]},"path":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"minItems":1,"maxItems":3}},"required":["type","sourceId","path"]},{"type":"object","properties":{"type":{"type":"string","const":"value"},"value":{"type":"string","maxLength":65536}},"required":["type","value"]}]},"description":"Where each evaluator input reads its value, keyed by input name. Inputs left out are unmapped; a required input left unmapped refuses the run."}},"required":["id","evaluatorId","required","mappings"],"description":"One evaluator that runs after every scenario run, with where each of its inputs reads from."},"maxItems":20,"description":"The full list of evaluators attached to the suite. An evaluator the project does not hold answers 422 suite_evaluator_not_found; a mapping the run cannot read answers 422 suite_evaluator_mapping_invalid."}}}}}},"security":[{"project_api_key":[]}]},"delete":{"operationId":"archiveTestSuite","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"The test suite that was archived."},"archived":{"type":"boolean","const":true,"description":"Always true once the suite is archived."}},"required":["id","archived"]}}}}},"description":"Archive a test suite. The scenarios filed in it are archived with it, in one step, because the suite is where they live.","tags":["Test Suites"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1},"required":true,"description":"The test suite id."}],"security":[{"project_api_key":[]}]}},"/api/v1/test-suites/{id}/run":{"post":{"operationId":"runTestSuite","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"scheduled":{"type":"boolean","description":"True once the runs are queued."},"batchRunId":{"type":"string","description":"The id of this batch. Every run started here carries it."},"setId":{"type":"string","description":"The result set the batch is filed under in the platform."},"jobCount":{"type":"number","description":"How many runs were queued."},"skippedArchived":{"type":"object","properties":{"scenarios":{"type":"array","items":{"type":"string"},"description":"Scenarios left out because they are archived."},"targets":{"type":"array","items":{"type":"string"},"description":"Targets left out because they are archived."}},"required":["scenarios","targets"],"description":"What the run left out, and why."},"items":{"type":"array","items":{"type":"object","properties":{"scenarioRunId":{"type":"string","description":"The id of this single run."},"scenarioId":{"type":"string","description":"The scenario that was run."},"target":{"type":"object","properties":{"type":{"type":"string","enum":["prompt","http","code","workflow","connected","voice"],"description":"What kind of thing the scenarios run against. A connected agent is one registered from code with the SDK."},"referenceId":{"type":"string","description":"The id of the prompt, agent or workflow to run against. A connected target may also say <name>@<environment>, for example support-agent@production, which resolves to the agent id."},"runParameters":{"type":"object","additionalProperties":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"description":"Parameter values this target alone runs with, by name. They are merged over the run-level parameters and the target wins, so two targets may name the same agent with different values: that is how one run compares one agent on two models, and the results show one column for each target."}},"required":["type","referenceId"],"description":"What it was run against."},"name":{"type":["string","null"],"description":"The scenario name, when known."}},"required":["scenarioRunId","scenarioId","target","name"]},"description":"Every run this call queued."},"runPlanId":{"type":"string","description":"The run plan this run was filed under."},"planName":{"type":"string","description":"The name that plan answers to."},"created":{"type":"boolean","description":"True when this run created the plan, false when it joined a plan already there."},"platformUrl":{"type":"string","format":"uri","description":"Where to watch this run in the LangWatch platform."}},"required":["scheduled","batchRunId","setId","jobCount","skippedArchived","items","runPlanId","planName","created","platformUrl"]}}}}},"description":"Run every scenario filed in the test suite against the targets sent with the request. The run is filed under a run plan named after the suite and its targets unless a name is sent. A request that names no target answers 422 suite_targets_required.","summary":"Run a test suite","tags":["Test Suites"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1},"required":true,"description":"The test suite id."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"targets":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["prompt","http","code","workflow","connected","voice"],"description":"What kind of thing the scenarios run against. A connected agent is one registered from code with the SDK."},"referenceId":{"type":"string","description":"The id of the prompt, agent or workflow to run against. A connected target may also say <name>@<environment>, for example support-agent@production, which resolves to the agent id."},"runParameters":{"type":"object","additionalProperties":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"description":"Parameter values this target alone runs with, by name. They are merged over the run-level parameters and the target wins, so two targets may name the same agent with different values: that is how one run compares one agent on two models, and the results show one column for each target."}},"required":["type","referenceId"]},"description":"The prompts, agents or workflows the suite runs against. A test suite stores none of its own, so a run states them. Every target runs every scenario, so naming more than one compares them in the same run."},"name":{"type":"string","minLength":1,"maxLength":200,"description":"The run plan this run joins or creates. Leave it out and the name is derived from the suite name and the targets."},"repeatCount":{"type":"integer","minimum":1,"maximum":5,"description":"How many times each scenario and target pairing runs. Between 1 and 5; defaults to 1."},"simulatorModel":{"type":["string","null"],"pattern":"^[a-zA-Z0-9_-]+(?:\\/[^\\s/]+)+$","maxLength":200,"description":"The model that plays the user for every scenario in this run. Leave it out for the scenario or project default."},"judgeModel":{"type":["string","null"],"pattern":"^[a-zA-Z0-9_-]+(?:\\/[^\\s/]+)+$","maxLength":200,"description":"The model that judges every scenario in this run. Leave it out for the scenario or project default."},"idempotencyKey":{"type":"string","description":"Repeat the same key to make a retry join the batch the first call started instead of running everything again. Defaults to a new key per call."},"parameters":{"type":"object","additionalProperties":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},"description":"Constant values applied to every scenario in the run, e.g. a fixture id or a tenant. A value supplied here overrides the scenario's own default for that name, and a target that names the same parameter in its runParameters overrides it for that target."},"note":{"type":"string","maxLength":200,"description":"One short line describing why this batch was run, e.g. a commit hash or what you changed. It is stored on every run of the batch and shown beside the run in the platform. Up to 200 characters."}},"required":["targets"]}}}},"security":[{"project_api_key":[]}]}},"/api/teams":{"get":{"operationId":"getApiTeams","description":"List all non-archived teams for the organization (paginated)","responses":{},"parameters":[{"in":"query","name":"page","schema":{"type":"integer","exclusiveMinimum":0,"default":1}},{"in":"query","name":"limit","schema":{"type":"integer","exclusiveMinimum":0,"maximum":1000,"default":50}}],"security":[{"admin_api_key":[]}]},"post":{"operationId":"postApiTeams","description":"Create a new team that can group projects and members","responses":{},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255}},"required":["name"]}}}},"security":[{"admin_api_key":[]}]}},"/api/teams/{id}":{"get":{"operationId":"getApiTeamsById","description":"Get a team by its id","responses":{},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"admin_api_key":[]}]},"patch":{"operationId":"patchApiTeamsById","description":"Update a team by its id","responses":{},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"admin_api_key":[]}]},"delete":{"operationId":"deleteApiTeamsById","description":"Archive a team (soft-delete)","responses":{},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"admin_api_key":[]}]}},"/api/teams/{id}/members":{"get":{"operationId":"getApiTeamsByIdMembers","description":"List members of a team","responses":{},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"admin_api_key":[]}]},"post":{"operationId":"postApiTeamsByIdMembers","description":"Add a member to a team","responses":{},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"userId":{"type":"string","minLength":1},"role":{"type":"string","enum":["ADMIN","MEMBER","VIEWER","CUSTOM"],"default":"MEMBER"}},"required":["userId"]}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"admin_api_key":[]}]}},"/api/teams/{id}/members/{userId}":{"delete":{"operationId":"deleteApiTeamsByIdMembersByUserId","description":"Remove a member from a team","responses":{},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true},{"schema":{"type":"string"},"in":"path","name":"userId","required":true}],"security":[{"admin_api_key":[]}]}},"/api/teams/{id}/projects":{"get":{"operationId":"getApiTeamsByIdProjects","description":"List projects in a team","responses":{},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"admin_api_key":[]}]}},"/api/groups":{"get":{"operationId":"getApiGroups","description":"List all groups for the organization","responses":{},"parameters":[{"in":"query","name":"page","schema":{"type":"integer","exclusiveMinimum":0,"default":1}},{"in":"query","name":"limit","schema":{"type":"integer","exclusiveMinimum":0,"maximum":1000,"default":50}}],"security":[{"admin_api_key":[]}]},"post":{"operationId":"postApiGroups","description":"Create a new group","responses":{},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100},"bindings":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string","enum":["ADMIN","MEMBER","VIEWER","CUSTOM"]},"customRoleId":{"type":"string"},"scopeType":{"type":"string","enum":["ORGANIZATION","TEAM","PROJECT"]},"scopeId":{"type":"string","minLength":1}},"required":["role","scopeType","scopeId"]}},"memberIds":{"type":"array","items":{"type":"string"}}},"required":["name"]}}}},"security":[{"admin_api_key":[]}]}},"/api/groups/{id}":{"get":{"operationId":"getApiGroupsById","description":"Get a group with members and bindings","responses":{},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"admin_api_key":[]}]},"patch":{"operationId":"patchApiGroupsById","description":"Rename a group","responses":{},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100}},"required":["name"]}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"admin_api_key":[]}]},"delete":{"operationId":"deleteApiGroupsById","description":"Delete a group","responses":{},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"admin_api_key":[]}]}},"/api/groups/{id}/members":{"get":{"operationId":"getApiGroupsByIdMembers","description":"List members of a group","responses":{},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"admin_api_key":[]}]},"post":{"operationId":"postApiGroupsByIdMembers","description":"Add a member to a group","responses":{},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"userId":{"type":"string","minLength":1}},"required":["userId"]}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"admin_api_key":[]}]}},"/api/groups/{id}/members/{userId}":{"delete":{"operationId":"deleteApiGroupsByIdMembersByUserId","description":"Remove a member from a group","responses":{},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true},{"schema":{"type":"string"},"in":"path","name":"userId","required":true}],"security":[{"admin_api_key":[]}]}},"/api/groups/{id}/bindings":{"get":{"operationId":"getApiGroupsByIdBindings","description":"List role bindings for a group","responses":{},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"admin_api_key":[]}]},"post":{"operationId":"postApiGroupsByIdBindings","description":"Add a role binding to a group","responses":{},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"role":{"type":"string","enum":["ADMIN","MEMBER","VIEWER","CUSTOM"]},"customRoleId":{"type":"string"},"scopeType":{"type":"string","enum":["ORGANIZATION","TEAM","PROJECT"]},"scopeId":{"type":"string","minLength":1}},"required":["role","scopeType","scopeId"]}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"admin_api_key":[]}]}},"/api/groups/{id}/bindings/{bindingId}":{"delete":{"operationId":"deleteApiGroupsByIdBindingsByBindingId","description":"Remove a role binding from a group","responses":{},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true},{"schema":{"type":"string"},"in":"path","name":"bindingId","required":true}],"security":[{"admin_api_key":[]}]}},"/api/traces/search":{"post":{"operationId":"postApiTracesSearch","description":"Search traces for a project","responses":{"200":{"description":"Matching traces with pagination","content":{"application/json":{"schema":{"type":"object","properties":{"traces":{"type":"array","items":{}},"pagination":{"type":"object","properties":{"totalHits":{"type":"number"},"scrollId":{"type":"string"},"skipped":{"type":"number","description":"Number of traces dropped from this page because they failed to serialize. Present only when non-zero, so a caller can tell that traces.length is below the page size for a reason other than reaching the end of the result set."},"updatedThrough":{"type":"number","description":"Only when dateField is 'updated'. Epoch milliseconds: the upper bound this scroll actually covered, which is at or before the endDate you asked for. The scroll reads every trace as of the moment it started, so anything written after that instant belongs to the next pull. Start your next incremental pull from this value — resuming from the endDate you requested would step over the difference and lose those traces. The bound is inclusive on both sides, so a trace last written at exactly this millisecond arrives in this pull and again in the next one: pulls are at-least-once, and applying them idempotently is what keeps that from becoming a duplicate."}},"required":["totalHits"]},"schema":{"type":"object","properties":{"from":{"type":"string"},"columns":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"type":{"type":"string"},"collection":{"type":"boolean"}},"required":["path","type","collection"]}}},"required":["from","columns"],"description":"Present only when 'select' is provided. Describes the resolved columns — the dotted path, its value type, and whether it belongs to a nested child collection — so callers can pre-allocate a typed reader."}},"required":["traces","pagination"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"query":{"type":"string"},"filters":{"type":"object","properties":{"topics.topics":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"topics.subtopics":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"metadata.user_id":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"metadata.thread_id":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"metadata.customer_id":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"metadata.labels":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"metadata.key":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"metadata.value":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"metadata.prompt_ids":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"traces.origin":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"traces.error":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"traces.name":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"spans.type":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"spans.model":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.evaluator_id":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.evaluator_id.guardrails_only":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.evaluator_id.has_passed":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.evaluator_id.has_score":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.evaluator_id.has_label":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.passed":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.score":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.state":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"evaluations.label":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"events.event_type":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"events.metrics.key":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"events.metrics.value":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"events.event_details.key":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]},"annotations.hasAnnotation":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]}},"additionalProperties":false,"default":{}},"traceIds":{"type":"array","items":{"type":"string"}},"negateFilters":{"type":"boolean"},"excludeOrigins":{"type":"array","items":{"type":"string"}},"pageOffset":{"type":"number","description":"Removed. Offset pagination is no longer supported and any value other than 0 is rejected. Page with the scrollId returned by the previous response instead. The field remains on the schema so that sending it produces an explanatory error rather than being silently discarded."},"pageSize":{"type":"integer","exclusiveMinimum":0},"groupBy":{"type":"string"},"sortBy":{"type":"string"},"sortDirection":{"type":"string"},"updatedAt":{"type":"number"},"scrollId":{"type":["string","null"]},"startDate":{"anyOf":[{"type":"number"},{"type":"string"}]},"endDate":{"anyOf":[{"type":"number"},{"type":"string"}]},"format":{"type":"string","enum":["digest","json"],"description":"Output format: 'digest' (AI-readable trace digest) or 'json' (full raw data)"},"includeSpans":{"type":"boolean","description":"When true, fetches full span data for each trace. Useful for bulk export. Default false."},"llmMode":{"type":"boolean"},"filter":{"type":"string","maxLength":4000,"description":"A trace filter string in the same language the Trace Explorer's search bar speaks — `status:error AND model:gpt-*`, `trace.attribute.langwatch.user_id:alice`, `evaluatorVerdict:fail`, a quoted phrase for free text. It is combined with `filters`, `query` and `traceIds` rather than replacing any of them, so every condition you send must hold. `GET /api/v1/query/reference` lists every field and the syntax; `GET /api/traces/facets` says what values a field actually holds. A malformed filter, or one naming a field the language does not have, is a 422 that names the field."},"dateField":{"type":"string","enum":["occurred","updated"],"default":"occurred","description":"Which timestamp the startDate/endDate window filters on. 'occurred' (default) selects traces by when they happened. 'updated' selects traces by when they were last modified — use this for incremental ETL ('give me everything changed since my last pull'), since a trace can occur long before it gains a later evaluation or annotation."},"from":{"type":"string","enum":["traces"],"default":"traces","description":"Entity root to read from. Only 'traces' is supported today; defaults to 'traces' when omitted."},"select":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"minItems":1,"maxItems":200,"description":"Flat list of dotted-path columns to project, e.g. ['trace_id','metadata.user_id','events.type','evaluations.score']. Paths group by root in the response: scalar fields stay top-level, 'metadata.*' nests under a metadata object, and 'events.*'/'annotations.*'/'evaluations.*' return as nested arrays (one row per trace). When present, the response gains a top-level 'schema' field describing the resolved columns. When omitted, the response is unchanged from the legacy shape."}},"required":["startDate","endDate"]}}}},"security":[{"project_api_key":[]}]}},"/api/traces/facets":{"get":{"operationId":"getApiTracesFacets","tags":["Traces"],"summary":"Discover what the trace filter fields hold","description":"What the trace filter fields actually hold in THIS project, which the filter language's own reference deliberately does not carry: values are tenant data, they move under you, and reading them all costs about thirty aggregate queries.\n\nTwo answers from one door. Without `field` you get the discovery payload: every facet this project has, each with its top values and counts, plus the range bounds for the numeric ones. With `field` you get one field's values, paged, filtered by `prefix`.\n\nThe values are cached and refreshed in the background, so a cold project answers `pending: true` with the payload it has; call again shortly for the computed one.\n\nUse it whenever you are unsure how a value is spelled. `GET /api/v1/query/reference` lists the fields and their fixed vocabularies; only this endpoint knows the open ones.","parameters":[{"in":"query","name":"field","schema":{"type":"string","minLength":1,"maxLength":512}},{"in":"query","name":"prefix","schema":{"type":"string","maxLength":512}},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":1000,"default":50}},{"in":"query","name":"offset","schema":{"type":"integer","minimum":0,"default":0}},{"in":"query","name":"startDate","schema":{"type":"string"}},{"in":"query","name":"endDate","schema":{"type":"string"}}],"responses":{"200":{"description":"Without `field`, every facet the project has with its top values and whether the payload is still being computed. With `field`, that field's values and counts plus the distinct total and whether more remain.","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"facets":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"kind":{"type":"string","enum":["categorical","range","dynamic_keys"]},"label":{"type":"string"},"group":{"type":"string"}},"required":["key","kind","label","group"],"additionalProperties":true}},"pending":{"type":"boolean","description":"True when the payload is still being computed and what you have is the last committed one, possibly empty. Call again shortly."}},"required":["facets","pending"]},{"type":"object","properties":{"values":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"},"count":{"type":"number"}},"required":["value","count"]}},"total":{"type":"number","description":"Distinct values the field holds in the window, before paging."},"hasMore":{"type":"boolean"}},"required":["values","total","hasMore"]}]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"403":{"description":"The field is an attribute key and this project hides captured input or output, so its values are not listed.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","const":"trace_attribute_values_withheld"},"message":{"type":"string"},"trace":{"type":"string"}},"required":["error","message"]}}}},"422":{"description":"The query did not name a facet with values to list. `fields` names the offending parameter and each reason carries what was received and what exists.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","const":"validation_error"},"message":{"type":"string"},"target":{"type":"string","const":"query"},"fields":{"type":"array","items":{"type":"string"}},"reasons":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"meta":{"type":"object","properties":{"field":{"type":"string"},"type":{"type":"string"},"message":{"type":"string"},"received":{"type":"string"},"expected":{"type":"array","items":{"type":"string"}}}}},"required":["code"]}},"trace":{"type":"string"}},"required":["error","message","target","fields","reasons"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"security":[{"project_api_key":[]}]}},"/api/traces/{traceId}/transcript":{"get":{"operationId":"getApiTracesByTraceIdTranscript","description":"Derived coding-agent transcript for a trace: what the agent did, in order, with per-call token and cost economics. Empty entries for traces without coding-agent content.","parameters":[{"name":"traceId","in":"path","description":"The trace ID — either the full 32-char ID or a unique prefix (≥ 8 chars). Prefix lookup is scoped to the authenticated project.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The transcript: ordered entries plus per-session totals and sub-agent tool counts","content":{"application/json":{"schema":{"type":"object","properties":{"agent":{"type":"string"},"sessionId":{"type":["string","null"]},"entries":{"type":"array","items":{"type":"object","additionalProperties":true}},"totals":{"type":"object","properties":{"modelCalls":{"type":"number"},"toolCalls":{"type":"number"},"tokens":{"type":"number"},"costUsd":{"type":"number"}},"required":["modelCalls","toolCalls","tokens","costUsd"]},"subAgents":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["agent","sessionId","entries","totals","subAgents"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Trace not found","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}},"409":{"description":"Ambiguous trace ID prefix — the prefix matches more than one trace","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"candidateTraceIds":{"type":"array","items":{"type":"string"}}},"required":["message","candidateTraceIds"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"security":[{"project_api_key":[]}]}},"/api/traces/{traceId}":{"get":{"operationId":"getApiTracesByTraceId","description":"Get a single trace by ID.","parameters":[{"name":"traceId","in":"path","description":"The trace ID — either the full 32-char ID or a unique prefix (≥ 8 chars). Prefix lookup is scoped to the authenticated project.","required":true,"schema":{"type":"string"}},{"name":"format","in":"query","description":"Output format: 'digest' (AI-readable) or 'json' (full raw data, default)","required":false,"schema":{"type":"string","enum":["digest","json"]}},{"name":"llmMode","in":"query","description":"Deprecated: use format=digest instead","required":false,"schema":{"type":"string","enum":["true","false","1","0"]}}],"responses":{"200":{"description":"Trace detail with spans, evaluations, and ASCII tree","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Trace not found","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}},"409":{"description":"Ambiguous trace ID prefix — the prefix matches more than one trace","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"candidateTraceIds":{"type":"array","items":{"type":"string"}}},"required":["message","candidateTraceIds"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"security":[{"project_api_key":[]}]}},"/api/traces/{traceId}/metadata":{"patch":{"operationId":"patchApiTracesByTraceIdMetadata","tags":["Traces"],"summary":"Update trace metadata","description":"Update metadata on a trace after creation. Inserts a synthetic span carrying the new attributes through the standard ingestion pipeline. New keys are added, existing keys are updated, missing keys are preserved. Labels replace entirely.","responses":{"200":{"description":"Metadata updated successfully","content":{"application/json":{"schema":{"type":"object","properties":{"traceId":{"type":"string"}},"required":["traceId"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"metadata":{"type":"object","additionalProperties":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"},{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{}}]}}},"required":["metadata"]}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"traceId","required":true}],"security":[{"project_api_key":[]}]}},"/api/triggers":{"get":{"operationId":"getApiTriggers","description":"List the project's automations, newest first. Paused automations are included.","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"action":{"type":"string","enum":["SEND_EMAIL","ADD_TO_DATASET","ADD_TO_ANNOTATION_QUEUE","SEND_SLACK_MESSAGE","SEND_WEBHOOK"]},"actionParams":{"type":"object","additionalProperties":{},"description":"Where this automation delivers, with every credential value replaced by the `[redacted]` placeholder. Which channel is configured, which destination is set and which header names are in play all survive; the values never leave; a Slack automation names its connection by `slackIntegrationId` and carries no secret. Sending the placeholder back on an update keeps the stored value. The rule this automation fires by is not here — it is stated in `graphAlert` or `report`, and sending it in this field is refused."},"graphAlert":{"type":["object","null"],"properties":{"threshold":{"type":"number"},"operator":{"type":"string","enum":["gt","lt","gte","lte","eq"]},"timePeriod":{"anyOf":[{"type":"number","const":1},{"type":"number","const":5},{"type":"number","const":15},{"type":"number","const":30},{"type":"number","const":60},{"type":"number","const":1440}]},"seriesName":{"type":"string","minLength":1}},"required":["threshold","operator","timePeriod","seriesName"],"description":"The rule an alert fires by. Null for anything that is not one."},"report":{"type":["object","null"],"properties":{"source":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"dashboard"},"dashboardId":{"type":"string","minLength":1}},"required":["kind","dashboardId"]},{"type":"object","properties":{"kind":{"type":"string","const":"customGraph"},"customGraphId":{"type":"string","minLength":1}},"required":["kind","customGraphId"]},{"type":"object","properties":{"kind":{"type":"string","const":"traceQuery"},"filters":{"type":"object","additionalProperties":{},"default":{}},"metric":{"type":"string"},"topN":{"type":"integer","minimum":1,"maximum":100,"default":5}},"required":["kind","filters","topN"]}]},"schedule":{"type":"object","properties":{"cron":{"type":"string","minLength":1,"maxLength":120},"timezone":{"type":"string","minLength":1,"maxLength":64}},"required":["cron","timezone"]},"compareToPrevious":{"type":"boolean","default":false}},"required":["source","schedule","compareToPrevious"],"description":"What a report renders and when. Null for anything else."},"filters":{"type":"object","additionalProperties":{}},"filterQuery":{"type":["string","null"]},"kind":{"type":"string","enum":["AUTOMATION","ALERT","REPORT"],"description":"What this automation is about: matching traces, a metric crossing a threshold, or a schedule."},"customGraphId":{"type":["string","null"]},"notificationCadence":{"type":["string","null"]},"traceDebounceMs":{"type":["number","null"]},"templates":{"type":"object","properties":{"slackTemplateType":{"type":["string","null"],"enum":["string","block_kit",null]},"slackTemplate":{"type":["string","null"]},"emailSubjectTemplate":{"type":["string","null"]},"emailBodyTemplate":{"type":["string","null"]}},"description":"The Liquid templates this automation's message is rendered from. Absent fields render the LangWatch default for the channel."},"active":{"type":"boolean"},"message":{"type":["string","null"]},"alertType":{"type":["string","null"],"enum":["CRITICAL","WARNING","INFO",null]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"platformUrl":{"type":"string","format":"uri"}},"required":["id","name","action","actionParams","graphAlert","report","filters","filterQuery","kind","customGraphId","notificationCadence","traceDebounceMs","templates","active","message","alertType","createdAt","updatedAt","platformUrl"]}}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"security":[{"project_api_key":[]}]},"post":{"operationId":"postApiTriggers","description":"Create an automation. Send `customGraphId` + `graphAlert` for an alert on a metric, `report` for a scheduled report, or conditions for a trace automation. The delivery channel is fixed at creation.","responses":{"201":{"description":"Trigger created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"action":{"type":"string","enum":["SEND_EMAIL","ADD_TO_DATASET","ADD_TO_ANNOTATION_QUEUE","SEND_SLACK_MESSAGE","SEND_WEBHOOK"]},"actionParams":{"type":"object","additionalProperties":{},"description":"Where this automation delivers, with every credential value replaced by the `[redacted]` placeholder. Which channel is configured, which destination is set and which header names are in play all survive; the values never leave; a Slack automation names its connection by `slackIntegrationId` and carries no secret. Sending the placeholder back on an update keeps the stored value. The rule this automation fires by is not here — it is stated in `graphAlert` or `report`, and sending it in this field is refused."},"graphAlert":{"type":["object","null"],"properties":{"threshold":{"type":"number"},"operator":{"type":"string","enum":["gt","lt","gte","lte","eq"]},"timePeriod":{"anyOf":[{"type":"number","const":1},{"type":"number","const":5},{"type":"number","const":15},{"type":"number","const":30},{"type":"number","const":60},{"type":"number","const":1440}]},"seriesName":{"type":"string","minLength":1}},"required":["threshold","operator","timePeriod","seriesName"],"description":"The rule an alert fires by. Null for anything that is not one."},"report":{"type":["object","null"],"properties":{"source":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"dashboard"},"dashboardId":{"type":"string","minLength":1}},"required":["kind","dashboardId"]},{"type":"object","properties":{"kind":{"type":"string","const":"customGraph"},"customGraphId":{"type":"string","minLength":1}},"required":["kind","customGraphId"]},{"type":"object","properties":{"kind":{"type":"string","const":"traceQuery"},"filters":{"type":"object","additionalProperties":{},"default":{}},"metric":{"type":"string"},"topN":{"type":"integer","minimum":1,"maximum":100,"default":5}},"required":["kind","filters","topN"]}]},"schedule":{"type":"object","properties":{"cron":{"type":"string","minLength":1,"maxLength":120},"timezone":{"type":"string","minLength":1,"maxLength":64}},"required":["cron","timezone"]},"compareToPrevious":{"type":"boolean","default":false}},"required":["source","schedule","compareToPrevious"],"description":"What a report renders and when. Null for anything else."},"filters":{"type":"object","additionalProperties":{}},"filterQuery":{"type":["string","null"]},"kind":{"type":"string","enum":["AUTOMATION","ALERT","REPORT"],"description":"What this automation is about: matching traces, a metric crossing a threshold, or a schedule."},"customGraphId":{"type":["string","null"]},"notificationCadence":{"type":["string","null"]},"traceDebounceMs":{"type":["number","null"]},"templates":{"type":"object","properties":{"slackTemplateType":{"type":["string","null"],"enum":["string","block_kit",null]},"slackTemplate":{"type":["string","null"]},"emailSubjectTemplate":{"type":["string","null"]},"emailBodyTemplate":{"type":["string","null"]}},"description":"The Liquid templates this automation's message is rendered from. Absent fields render the LangWatch default for the channel."},"active":{"type":"boolean"},"message":{"type":["string","null"]},"alertType":{"type":["string","null"],"enum":["CRITICAL","WARNING","INFO",null]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"platformUrl":{"type":"string","format":"uri"}},"required":["id","name","action","actionParams","graphAlert","report","filters","filterQuery","kind","customGraphId","notificationCadence","traceDebounceMs","templates","active","message","alertType","createdAt","updatedAt","platformUrl"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"type":"string","const":"SEND_EMAIL"},"actionParams":{"type":"object","properties":{"members":{"type":"array","items":{"type":"string"},"minItems":1,"description":"Who receives the email. Any address, not only teammates."}},"required":["members"],"additionalProperties":true,"description":"Email delivery."},"name":{"type":"string","minLength":1},"filters":{"type":"object","additionalProperties":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]}},"filterQuery":{"type":["string","null"],"description":"The trace query this automation is about, in the syntax the traces view uses. When set it supersedes `filters`."},"message":{"type":"string"},"alertType":{"type":"string","enum":["CRITICAL","WARNING","INFO"]},"customGraphId":{"type":"string","description":"Set to make this an alert on that graph. `graphAlert` and `alertType` are then required."},"graphAlert":{"type":"object","properties":{"threshold":{"type":"number"},"operator":{"type":"string","enum":["gt","lt","gte","lte","eq"]},"timePeriod":{"anyOf":[{"type":"number","const":1},{"type":"number","const":5},{"type":"number","const":15},{"type":"number","const":30},{"type":"number","const":60},{"type":"number","const":1440}]},"seriesName":{"type":"string","minLength":1}},"required":["threshold","operator","timePeriod","seriesName"],"description":"The rule an alert fires by: series, operator, threshold, window."},"report":{"type":"object","properties":{"source":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"dashboard"},"dashboardId":{"type":"string","minLength":1}},"required":["kind","dashboardId"]},{"type":"object","properties":{"kind":{"type":"string","const":"customGraph"},"customGraphId":{"type":"string","minLength":1}},"required":["kind","customGraphId"]},{"type":"object","properties":{"kind":{"type":"string","const":"traceQuery"},"filters":{"type":"object","additionalProperties":{},"default":{}},"metric":{"type":"string"},"topN":{"type":"integer","minimum":1,"maximum":100,"default":5}},"required":["kind"]}]},"schedule":{"type":"object","properties":{"cron":{"type":"string","minLength":1,"maxLength":120},"timezone":{"type":"string","minLength":1,"maxLength":64}},"required":["cron","timezone"]},"compareToPrevious":{"type":"boolean","default":false}},"required":["source","schedule"],"description":"What a scheduled report renders and when it sends."},"templates":{"type":"object","properties":{"slackTemplateType":{"type":["string","null"],"enum":["string","block_kit",null]},"slackTemplate":{"type":["string","null"]},"emailSubjectTemplate":{"type":["string","null"]},"emailBodyTemplate":{"type":["string","null"]}},"description":"The Liquid templates this automation's message is rendered from. Absent fields render the LangWatch default for the channel."},"notificationCadence":{"type":"string","enum":["immediate","5min_digest","15min_digest","hourly_digest"],"description":"How often a notification automation is allowed to send. A new one starts on a five-minute digest, which is what keeps a broad condition from sending a message per matching trace."},"traceDebounceMs":{"type":"integer","minimum":0,"maximum":600000,"description":"How long to wait for a trace to settle before the conditions are read."}},"required":["action","actionParams","name"]},{"type":"object","properties":{"action":{"type":"string","const":"SEND_SLACK_MESSAGE"},"actionParams":{"type":"object","properties":{"slackIntegrationId":{"type":"string","description":"The Slack connection this automation posts through: an organization connection or one of this project's, listed under Settings, Integrations, Slack. A bot connection also needs `slackChannelId`; a webhook connection needs nothing else. Preferred over `slackWebhook` and `slackBotToken`, and what a read returns in their place."},"slackDelivery":{"type":"string","enum":["webhook","bot"],"description":"How the message reaches Slack. `webhook` posts to an incoming webhook URL, `bot` posts as the LangWatch Slack app. With `slackIntegrationId` it follows the connection's kind. Absent without a connection means `webhook`."},"slackWebhook":{"type":"string","description":"Legacy, accepted for one release: an incoming webhook URL, for `webhook` delivery. It is stored as a Slack connection (an existing one holding the same URL, else a new project connection) and the automation keeps only that connection's id. Send `slackIntegrationId` instead."},"slackChannelId":{"type":"string","description":"The channel the bot posts in, for a bot connection or `bot` delivery. Invite the LangWatch app to it first."},"slackBotToken":{"type":"string","description":"Legacy, accepted for one release: a bot token, for `bot` delivery. It is stored as a Slack connection (an existing one holding the same token, else a new project connection) and never reads back. Send `slackIntegrationId` instead."},"slackBotTokenSet":{"type":"boolean","description":"Legacy and ignored: no read returns it. An update that retypes no secret moves an automation's own stored secret into a connection."}},"additionalProperties":true,"description":"Slack delivery through a Slack connection (`slackIntegrationId`), plus `slackChannelId` when the connection is a bot."},"name":{"type":"string","minLength":1},"filters":{"type":"object","additionalProperties":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]}},"filterQuery":{"type":["string","null"],"description":"The trace query this automation is about, in the syntax the traces view uses. When set it supersedes `filters`."},"message":{"type":"string"},"alertType":{"type":"string","enum":["CRITICAL","WARNING","INFO"]},"customGraphId":{"type":"string","description":"Set to make this an alert on that graph. `graphAlert` and `alertType` are then required."},"graphAlert":{"type":"object","properties":{"threshold":{"type":"number"},"operator":{"type":"string","enum":["gt","lt","gte","lte","eq"]},"timePeriod":{"anyOf":[{"type":"number","const":1},{"type":"number","const":5},{"type":"number","const":15},{"type":"number","const":30},{"type":"number","const":60},{"type":"number","const":1440}]},"seriesName":{"type":"string","minLength":1}},"required":["threshold","operator","timePeriod","seriesName"],"description":"The rule an alert fires by: series, operator, threshold, window."},"report":{"type":"object","properties":{"source":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"dashboard"},"dashboardId":{"type":"string","minLength":1}},"required":["kind","dashboardId"]},{"type":"object","properties":{"kind":{"type":"string","const":"customGraph"},"customGraphId":{"type":"string","minLength":1}},"required":["kind","customGraphId"]},{"type":"object","properties":{"kind":{"type":"string","const":"traceQuery"},"filters":{"type":"object","additionalProperties":{},"default":{}},"metric":{"type":"string"},"topN":{"type":"integer","minimum":1,"maximum":100,"default":5}},"required":["kind"]}]},"schedule":{"type":"object","properties":{"cron":{"type":"string","minLength":1,"maxLength":120},"timezone":{"type":"string","minLength":1,"maxLength":64}},"required":["cron","timezone"]},"compareToPrevious":{"type":"boolean","default":false}},"required":["source","schedule"],"description":"What a scheduled report renders and when it sends."},"templates":{"type":"object","properties":{"slackTemplateType":{"type":["string","null"],"enum":["string","block_kit",null]},"slackTemplate":{"type":["string","null"]},"emailSubjectTemplate":{"type":["string","null"]},"emailBodyTemplate":{"type":["string","null"]}},"description":"The Liquid templates this automation's message is rendered from. Absent fields render the LangWatch default for the channel."},"notificationCadence":{"type":"string","enum":["immediate","5min_digest","15min_digest","hourly_digest"],"description":"How often a notification automation is allowed to send. A new one starts on a five-minute digest, which is what keeps a broad condition from sending a message per matching trace."},"traceDebounceMs":{"type":"integer","minimum":0,"maximum":600000,"description":"How long to wait for a trace to settle before the conditions are read."}},"required":["action","actionParams","name"]},{"type":"object","properties":{"action":{"type":"string","const":"SEND_WEBHOOK"},"actionParams":{"type":"object","properties":{"url":{"type":"string","description":"Where the request goes. https only, and not a private host."},"method":{"type":"string","enum":["POST","PUT","PATCH"],"description":"The HTTP method. Absent means POST."},"headers":{"type":"object","additionalProperties":{"type":"string"},"description":"Static headers sent with every delivery. The values are credentials: they read back as the placeholder, and sending the placeholder back keeps the stored ones. Changing `url` means sending the values again in the same request."},"bodyTemplate":{"type":["string","null"],"description":"A Liquid template for the body. Absent sends the standard LangWatch envelope for a JSON content type, and an empty body for any other."},"contentType":{"type":"string","description":"The `Content-Type` the delivery announces, which also decides how the body is treated: `application/json` (and any `+json` type) is checked and re-serialised; any other media type sends the rendered template verbatim. Absent means `application/json`."},"signingSecret":{"type":["string","null"],"description":"Signs every delivery so the receiver can verify it came from LangWatch. A credential: it reads back as the placeholder, and sending the placeholder back keeps the stored one."}},"required":["url"],"additionalProperties":true,"description":"Delivery to a customer endpoint over HTTP, with a body in any media type."},"name":{"type":"string","minLength":1},"filters":{"type":"object","additionalProperties":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]}},"filterQuery":{"type":["string","null"],"description":"The trace query this automation is about, in the syntax the traces view uses. When set it supersedes `filters`."},"message":{"type":"string"},"alertType":{"type":"string","enum":["CRITICAL","WARNING","INFO"]},"customGraphId":{"type":"string","description":"Set to make this an alert on that graph. `graphAlert` and `alertType` are then required."},"graphAlert":{"type":"object","properties":{"threshold":{"type":"number"},"operator":{"type":"string","enum":["gt","lt","gte","lte","eq"]},"timePeriod":{"anyOf":[{"type":"number","const":1},{"type":"number","const":5},{"type":"number","const":15},{"type":"number","const":30},{"type":"number","const":60},{"type":"number","const":1440}]},"seriesName":{"type":"string","minLength":1}},"required":["threshold","operator","timePeriod","seriesName"],"description":"The rule an alert fires by: series, operator, threshold, window."},"report":{"type":"object","properties":{"source":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"dashboard"},"dashboardId":{"type":"string","minLength":1}},"required":["kind","dashboardId"]},{"type":"object","properties":{"kind":{"type":"string","const":"customGraph"},"customGraphId":{"type":"string","minLength":1}},"required":["kind","customGraphId"]},{"type":"object","properties":{"kind":{"type":"string","const":"traceQuery"},"filters":{"type":"object","additionalProperties":{},"default":{}},"metric":{"type":"string"},"topN":{"type":"integer","minimum":1,"maximum":100,"default":5}},"required":["kind"]}]},"schedule":{"type":"object","properties":{"cron":{"type":"string","minLength":1,"maxLength":120},"timezone":{"type":"string","minLength":1,"maxLength":64}},"required":["cron","timezone"]},"compareToPrevious":{"type":"boolean","default":false}},"required":["source","schedule"],"description":"What a scheduled report renders and when it sends."},"templates":{"type":"object","properties":{"slackTemplateType":{"type":["string","null"],"enum":["string","block_kit",null]},"slackTemplate":{"type":["string","null"]},"emailSubjectTemplate":{"type":["string","null"]},"emailBodyTemplate":{"type":["string","null"]}},"description":"The Liquid templates this automation's message is rendered from. Absent fields render the LangWatch default for the channel."},"notificationCadence":{"type":"string","enum":["immediate","5min_digest","15min_digest","hourly_digest"],"description":"How often a notification automation is allowed to send. A new one starts on a five-minute digest, which is what keeps a broad condition from sending a message per matching trace."},"traceDebounceMs":{"type":"integer","minimum":0,"maximum":600000,"description":"How long to wait for a trace to settle before the conditions are read."}},"required":["action","actionParams","name"]},{"type":"object","properties":{"action":{"type":"string","const":"ADD_TO_DATASET"},"actionParams":{"type":"object","properties":{"datasetId":{"type":"string","description":"The dataset matched traces are appended to."},"datasetMapping":{"type":"object","properties":{"mapping":{"type":"object","additionalProperties":{}},"expansions":{"type":"array","items":{"type":"string"}}},"required":["mapping"],"description":"How a trace becomes a row in that dataset."}},"required":["datasetId","datasetMapping"],"additionalProperties":true,"description":"Append matched traces to a dataset."},"name":{"type":"string","minLength":1},"filters":{"type":"object","additionalProperties":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]}},"filterQuery":{"type":["string","null"],"description":"The trace query this automation is about, in the syntax the traces view uses. When set it supersedes `filters`."},"message":{"type":"string"},"alertType":{"type":"string","enum":["CRITICAL","WARNING","INFO"]},"customGraphId":{"type":"string","description":"Set to make this an alert on that graph. `graphAlert` and `alertType` are then required."},"graphAlert":{"type":"object","properties":{"threshold":{"type":"number"},"operator":{"type":"string","enum":["gt","lt","gte","lte","eq"]},"timePeriod":{"anyOf":[{"type":"number","const":1},{"type":"number","const":5},{"type":"number","const":15},{"type":"number","const":30},{"type":"number","const":60},{"type":"number","const":1440}]},"seriesName":{"type":"string","minLength":1}},"required":["threshold","operator","timePeriod","seriesName"],"description":"The rule an alert fires by: series, operator, threshold, window."},"report":{"type":"object","properties":{"source":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"dashboard"},"dashboardId":{"type":"string","minLength":1}},"required":["kind","dashboardId"]},{"type":"object","properties":{"kind":{"type":"string","const":"customGraph"},"customGraphId":{"type":"string","minLength":1}},"required":["kind","customGraphId"]},{"type":"object","properties":{"kind":{"type":"string","const":"traceQuery"},"filters":{"type":"object","additionalProperties":{},"default":{}},"metric":{"type":"string"},"topN":{"type":"integer","minimum":1,"maximum":100,"default":5}},"required":["kind"]}]},"schedule":{"type":"object","properties":{"cron":{"type":"string","minLength":1,"maxLength":120},"timezone":{"type":"string","minLength":1,"maxLength":64}},"required":["cron","timezone"]},"compareToPrevious":{"type":"boolean","default":false}},"required":["source","schedule"],"description":"What a scheduled report renders and when it sends."},"templates":{"type":"object","properties":{"slackTemplateType":{"type":["string","null"],"enum":["string","block_kit",null]},"slackTemplate":{"type":["string","null"]},"emailSubjectTemplate":{"type":["string","null"]},"emailBodyTemplate":{"type":["string","null"]}},"description":"The Liquid templates this automation's message is rendered from. Absent fields render the LangWatch default for the channel."},"notificationCadence":{"type":"string","enum":["immediate","5min_digest","15min_digest","hourly_digest"],"description":"How often a notification automation is allowed to send. A new one starts on a five-minute digest, which is what keeps a broad condition from sending a message per matching trace."},"traceDebounceMs":{"type":"integer","minimum":0,"maximum":600000,"description":"How long to wait for a trace to settle before the conditions are read."}},"required":["action","actionParams","name"]},{"type":"object","properties":{"action":{"type":"string","const":"ADD_TO_ANNOTATION_QUEUE"},"actionParams":{"type":"object","properties":{"annotators":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"]},"minItems":1,"description":"Who the queued items go to."}},"required":["annotators"],"additionalProperties":true,"description":"Queue matched traces for a person to label."},"name":{"type":"string","minLength":1},"filters":{"type":"object","additionalProperties":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]}},"filterQuery":{"type":["string","null"],"description":"The trace query this automation is about, in the syntax the traces view uses. When set it supersedes `filters`."},"message":{"type":"string"},"alertType":{"type":"string","enum":["CRITICAL","WARNING","INFO"]},"customGraphId":{"type":"string","description":"Set to make this an alert on that graph. `graphAlert` and `alertType` are then required."},"graphAlert":{"type":"object","properties":{"threshold":{"type":"number"},"operator":{"type":"string","enum":["gt","lt","gte","lte","eq"]},"timePeriod":{"anyOf":[{"type":"number","const":1},{"type":"number","const":5},{"type":"number","const":15},{"type":"number","const":30},{"type":"number","const":60},{"type":"number","const":1440}]},"seriesName":{"type":"string","minLength":1}},"required":["threshold","operator","timePeriod","seriesName"],"description":"The rule an alert fires by: series, operator, threshold, window."},"report":{"type":"object","properties":{"source":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"dashboard"},"dashboardId":{"type":"string","minLength":1}},"required":["kind","dashboardId"]},{"type":"object","properties":{"kind":{"type":"string","const":"customGraph"},"customGraphId":{"type":"string","minLength":1}},"required":["kind","customGraphId"]},{"type":"object","properties":{"kind":{"type":"string","const":"traceQuery"},"filters":{"type":"object","additionalProperties":{},"default":{}},"metric":{"type":"string"},"topN":{"type":"integer","minimum":1,"maximum":100,"default":5}},"required":["kind"]}]},"schedule":{"type":"object","properties":{"cron":{"type":"string","minLength":1,"maxLength":120},"timezone":{"type":"string","minLength":1,"maxLength":64}},"required":["cron","timezone"]},"compareToPrevious":{"type":"boolean","default":false}},"required":["source","schedule"],"description":"What a scheduled report renders and when it sends."},"templates":{"type":"object","properties":{"slackTemplateType":{"type":["string","null"],"enum":["string","block_kit",null]},"slackTemplate":{"type":["string","null"]},"emailSubjectTemplate":{"type":["string","null"]},"emailBodyTemplate":{"type":["string","null"]}},"description":"The Liquid templates this automation's message is rendered from. Absent fields render the LangWatch default for the channel."},"notificationCadence":{"type":"string","enum":["immediate","5min_digest","15min_digest","hourly_digest"],"description":"How often a notification automation is allowed to send. A new one starts on a five-minute digest, which is what keeps a broad condition from sending a message per matching trace."},"traceDebounceMs":{"type":"integer","minimum":0,"maximum":600000,"description":"How long to wait for a trace to settle before the conditions are read."}},"required":["action","actionParams","name"]}]}}}},"security":[{"project_api_key":[]}]}},"/api/triggers/{id}":{"get":{"operationId":"getApiTriggersById","description":"Get a trigger by its ID","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"action":{"type":"string","enum":["SEND_EMAIL","ADD_TO_DATASET","ADD_TO_ANNOTATION_QUEUE","SEND_SLACK_MESSAGE","SEND_WEBHOOK"]},"actionParams":{"type":"object","additionalProperties":{},"description":"Where this automation delivers, with every credential value replaced by the `[redacted]` placeholder. Which channel is configured, which destination is set and which header names are in play all survive; the values never leave; a Slack automation names its connection by `slackIntegrationId` and carries no secret. Sending the placeholder back on an update keeps the stored value. The rule this automation fires by is not here — it is stated in `graphAlert` or `report`, and sending it in this field is refused."},"graphAlert":{"type":["object","null"],"properties":{"threshold":{"type":"number"},"operator":{"type":"string","enum":["gt","lt","gte","lte","eq"]},"timePeriod":{"anyOf":[{"type":"number","const":1},{"type":"number","const":5},{"type":"number","const":15},{"type":"number","const":30},{"type":"number","const":60},{"type":"number","const":1440}]},"seriesName":{"type":"string","minLength":1}},"required":["threshold","operator","timePeriod","seriesName"],"description":"The rule an alert fires by. Null for anything that is not one."},"report":{"type":["object","null"],"properties":{"source":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"dashboard"},"dashboardId":{"type":"string","minLength":1}},"required":["kind","dashboardId"]},{"type":"object","properties":{"kind":{"type":"string","const":"customGraph"},"customGraphId":{"type":"string","minLength":1}},"required":["kind","customGraphId"]},{"type":"object","properties":{"kind":{"type":"string","const":"traceQuery"},"filters":{"type":"object","additionalProperties":{},"default":{}},"metric":{"type":"string"},"topN":{"type":"integer","minimum":1,"maximum":100,"default":5}},"required":["kind","filters","topN"]}]},"schedule":{"type":"object","properties":{"cron":{"type":"string","minLength":1,"maxLength":120},"timezone":{"type":"string","minLength":1,"maxLength":64}},"required":["cron","timezone"]},"compareToPrevious":{"type":"boolean","default":false}},"required":["source","schedule","compareToPrevious"],"description":"What a report renders and when. Null for anything else."},"filters":{"type":"object","additionalProperties":{}},"filterQuery":{"type":["string","null"]},"kind":{"type":"string","enum":["AUTOMATION","ALERT","REPORT"],"description":"What this automation is about: matching traces, a metric crossing a threshold, or a schedule."},"customGraphId":{"type":["string","null"]},"notificationCadence":{"type":["string","null"]},"traceDebounceMs":{"type":["number","null"]},"templates":{"type":"object","properties":{"slackTemplateType":{"type":["string","null"],"enum":["string","block_kit",null]},"slackTemplate":{"type":["string","null"]},"emailSubjectTemplate":{"type":["string","null"]},"emailBodyTemplate":{"type":["string","null"]}},"description":"The Liquid templates this automation's message is rendered from. Absent fields render the LangWatch default for the channel."},"active":{"type":"boolean"},"message":{"type":["string","null"]},"alertType":{"type":["string","null"],"enum":["CRITICAL","WARNING","INFO",null]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"platformUrl":{"type":"string","format":"uri"}},"required":["id","name","action","actionParams","graphAlert","report","filters","filterQuery","kind","customGraphId","notificationCadence","traceDebounceMs","templates","active","message","alertType","createdAt","updatedAt","platformUrl"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Trigger not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]},"patch":{"operationId":"patchApiTriggersById","description":"Update an automation. Every field is optional and what is left out is left alone, except `actionParams`, which replaces the delivery configuration as a whole. The delivery channel and an alert's graph cannot be changed.","responses":{"200":{"description":"Trigger updated","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"action":{"type":"string","enum":["SEND_EMAIL","ADD_TO_DATASET","ADD_TO_ANNOTATION_QUEUE","SEND_SLACK_MESSAGE","SEND_WEBHOOK"]},"actionParams":{"type":"object","additionalProperties":{},"description":"Where this automation delivers, with every credential value replaced by the `[redacted]` placeholder. Which channel is configured, which destination is set and which header names are in play all survive; the values never leave; a Slack automation names its connection by `slackIntegrationId` and carries no secret. Sending the placeholder back on an update keeps the stored value. The rule this automation fires by is not here — it is stated in `graphAlert` or `report`, and sending it in this field is refused."},"graphAlert":{"type":["object","null"],"properties":{"threshold":{"type":"number"},"operator":{"type":"string","enum":["gt","lt","gte","lte","eq"]},"timePeriod":{"anyOf":[{"type":"number","const":1},{"type":"number","const":5},{"type":"number","const":15},{"type":"number","const":30},{"type":"number","const":60},{"type":"number","const":1440}]},"seriesName":{"type":"string","minLength":1}},"required":["threshold","operator","timePeriod","seriesName"],"description":"The rule an alert fires by. Null for anything that is not one."},"report":{"type":["object","null"],"properties":{"source":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"dashboard"},"dashboardId":{"type":"string","minLength":1}},"required":["kind","dashboardId"]},{"type":"object","properties":{"kind":{"type":"string","const":"customGraph"},"customGraphId":{"type":"string","minLength":1}},"required":["kind","customGraphId"]},{"type":"object","properties":{"kind":{"type":"string","const":"traceQuery"},"filters":{"type":"object","additionalProperties":{},"default":{}},"metric":{"type":"string"},"topN":{"type":"integer","minimum":1,"maximum":100,"default":5}},"required":["kind","filters","topN"]}]},"schedule":{"type":"object","properties":{"cron":{"type":"string","minLength":1,"maxLength":120},"timezone":{"type":"string","minLength":1,"maxLength":64}},"required":["cron","timezone"]},"compareToPrevious":{"type":"boolean","default":false}},"required":["source","schedule","compareToPrevious"],"description":"What a report renders and when. Null for anything else."},"filters":{"type":"object","additionalProperties":{}},"filterQuery":{"type":["string","null"]},"kind":{"type":"string","enum":["AUTOMATION","ALERT","REPORT"],"description":"What this automation is about: matching traces, a metric crossing a threshold, or a schedule."},"customGraphId":{"type":["string","null"]},"notificationCadence":{"type":["string","null"]},"traceDebounceMs":{"type":["number","null"]},"templates":{"type":"object","properties":{"slackTemplateType":{"type":["string","null"],"enum":["string","block_kit",null]},"slackTemplate":{"type":["string","null"]},"emailSubjectTemplate":{"type":["string","null"]},"emailBodyTemplate":{"type":["string","null"]}},"description":"The Liquid templates this automation's message is rendered from. Absent fields render the LangWatch default for the channel."},"active":{"type":"boolean"},"message":{"type":["string","null"]},"alertType":{"type":["string","null"],"enum":["CRITICAL","WARNING","INFO",null]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"platformUrl":{"type":"string","format":"uri"}},"required":["id","name","action","actionParams","graphAlert","report","filters","filterQuery","kind","customGraphId","notificationCadence","traceDebounceMs","templates","active","message","alertType","createdAt","updatedAt","platformUrl"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Trigger not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1},"active":{"type":"boolean"},"message":{"type":["string","null"]},"alertType":{"type":["string","null"],"enum":["CRITICAL","WARNING","INFO",null]},"filters":{"type":"object","additionalProperties":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}]}},"filterQuery":{"type":["string","null"],"description":"The trace query this automation is about, in the syntax the traces view uses. When set it supersedes `filters`."},"action":{"type":"string","enum":["SEND_EMAIL","ADD_TO_DATASET","ADD_TO_ANNOTATION_QUEUE","SEND_SLACK_MESSAGE","SEND_WEBHOOK"]},"customGraphId":{"type":["string","null"],"description":"The graph this alert watches, which an update cannot change. Accepted so that writing the read response back works; a different graph is refused. Create an alert on the other graph and delete this one."},"actionParams":{"anyOf":[{"type":"object","properties":{"members":{"type":"array","items":{"type":"string"},"minItems":1,"description":"Who receives the email. Any address, not only teammates."}},"required":["members"],"additionalProperties":true,"description":"Email delivery."},{"type":"object","properties":{"slackIntegrationId":{"type":"string","description":"The Slack connection this automation posts through: an organization connection or one of this project's, listed under Settings, Integrations, Slack. A bot connection also needs `slackChannelId`; a webhook connection needs nothing else. Preferred over `slackWebhook` and `slackBotToken`, and what a read returns in their place."},"slackDelivery":{"type":"string","enum":["webhook","bot"],"description":"How the message reaches Slack. `webhook` posts to an incoming webhook URL, `bot` posts as the LangWatch Slack app. With `slackIntegrationId` it follows the connection's kind. Absent without a connection means `webhook`."},"slackWebhook":{"type":"string","description":"Legacy, accepted for one release: an incoming webhook URL, for `webhook` delivery. It is stored as a Slack connection (an existing one holding the same URL, else a new project connection) and the automation keeps only that connection's id. Send `slackIntegrationId` instead."},"slackChannelId":{"type":"string","description":"The channel the bot posts in, for a bot connection or `bot` delivery. Invite the LangWatch app to it first."},"slackBotToken":{"type":"string","description":"Legacy, accepted for one release: a bot token, for `bot` delivery. It is stored as a Slack connection (an existing one holding the same token, else a new project connection) and never reads back. Send `slackIntegrationId` instead."},"slackBotTokenSet":{"type":"boolean","description":"Legacy and ignored: no read returns it. An update that retypes no secret moves an automation's own stored secret into a connection."}},"additionalProperties":true,"description":"Slack delivery through a Slack connection (`slackIntegrationId`), plus `slackChannelId` when the connection is a bot."},{"type":"object","properties":{"url":{"type":"string","description":"Where the request goes. https only, and not a private host."},"method":{"type":"string","enum":["POST","PUT","PATCH"],"description":"The HTTP method. Absent means POST."},"headers":{"type":"object","additionalProperties":{"type":"string"},"description":"Static headers sent with every delivery. The values are credentials: they read back as the placeholder, and sending the placeholder back keeps the stored ones. Changing `url` means sending the values again in the same request."},"bodyTemplate":{"type":["string","null"],"description":"A Liquid template for the body. Absent sends the standard LangWatch envelope for a JSON content type, and an empty body for any other."},"contentType":{"type":"string","description":"The `Content-Type` the delivery announces, which also decides how the body is treated: `application/json` (and any `+json` type) is checked and re-serialised; any other media type sends the rendered template verbatim. Absent means `application/json`."},"signingSecret":{"type":["string","null"],"description":"Signs every delivery so the receiver can verify it came from LangWatch. A credential: it reads back as the placeholder, and sending the placeholder back keeps the stored one."}},"required":["url"],"additionalProperties":true,"description":"Delivery to a customer endpoint over HTTP, with a body in any media type."},{"type":"object","properties":{"datasetId":{"type":"string","description":"The dataset matched traces are appended to."},"datasetMapping":{"type":"object","properties":{"mapping":{"type":"object","additionalProperties":{}},"expansions":{"type":"array","items":{"type":"string"}}},"required":["mapping"],"description":"How a trace becomes a row in that dataset."}},"required":["datasetId","datasetMapping"],"additionalProperties":true,"description":"Append matched traces to a dataset."},{"type":"object","properties":{"annotators":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"]},"minItems":1,"description":"Who the queued items go to."}},"required":["annotators"],"additionalProperties":true,"description":"Queue matched traces for a person to label."}],"description":"Replaces the delivery configuration as a whole rather than merging into it: send the fields this automation should have from now on, and anything left out is removed — omit `headers` and it delivers with none, omit `signingSecret` and its deliveries are no longer signed. The one exception is a credential the read hid: send back the `[redacted]` placeholder and the stored credential is kept (a Slack automation not yet on a connection has its stored secret moved into one), so reading an automation, changing one field and writing the whole object back is safe. Only this channel's fields are accepted; anything else is refused rather than dropped, and the rule this automation fires by belongs in `graphAlert` or `report`."},"graphAlert":{"type":"object","properties":{"threshold":{"type":"number"},"operator":{"type":"string","enum":["gt","lt","gte","lte","eq"]},"timePeriod":{"anyOf":[{"type":"number","const":1},{"type":"number","const":5},{"type":"number","const":15},{"type":"number","const":30},{"type":"number","const":60},{"type":"number","const":1440}]},"seriesName":{"type":"string","minLength":1}},"required":["threshold","operator","timePeriod","seriesName"],"description":"The rule this alert fires by. Only for an automation that is one."},"report":{"type":"object","properties":{"source":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"dashboard"},"dashboardId":{"type":"string","minLength":1}},"required":["kind","dashboardId"]},{"type":"object","properties":{"kind":{"type":"string","const":"customGraph"},"customGraphId":{"type":"string","minLength":1}},"required":["kind","customGraphId"]},{"type":"object","properties":{"kind":{"type":"string","const":"traceQuery"},"filters":{"type":"object","additionalProperties":{},"default":{}},"metric":{"type":"string"},"topN":{"type":"integer","minimum":1,"maximum":100,"default":5}},"required":["kind"]}]},"schedule":{"type":"object","properties":{"cron":{"type":"string","minLength":1,"maxLength":120},"timezone":{"type":"string","minLength":1,"maxLength":64}},"required":["cron","timezone"]},"compareToPrevious":{"type":"boolean","default":false}},"required":["source","schedule"],"description":"What this report renders and when. Only for one that is a report."},"templates":{"type":"object","properties":{"slackTemplateType":{"type":["string","null"],"enum":["string","block_kit",null]},"slackTemplate":{"type":["string","null"]},"emailSubjectTemplate":{"type":["string","null"]},"emailBodyTemplate":{"type":["string","null"]}},"description":"The Liquid templates this automation's message is rendered from. Absent fields render the LangWatch default for the channel."},"notificationCadence":{"type":"string","enum":["immediate","5min_digest","15min_digest","hourly_digest"],"description":"How often a notification automation is allowed to send. A new one starts on a five-minute digest, which is what keeps a broad condition from sending a message per matching trace."},"traceDebounceMs":{"type":"integer","minimum":0,"maximum":600000,"description":"How long to wait for a trace to settle before the conditions are read."}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]},"delete":{"operationId":"deleteApiTriggersById","description":"Delete (soft-delete) a trigger","responses":{"200":{"description":"Trigger deleted","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"deleted":{"type":"boolean"}},"required":["id","deleted"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Trigger not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]}},"/api/triggers/{id}/fires":{"get":{"operationId":"getApiTriggersByIdFires","description":"What this automation has done: its fires, newest first. Metadata only — no trace ids and no trace content. Send `nextCursor` back as `cursor` to read the page after this one.","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"fires":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"triggerId":{"type":"string"},"customGraphId":{"type":["string","null"]},"firedAt":{"type":"string"},"resolvedAt":{"type":["string","null"]}},"required":["id","triggerId","customGraphId","firedAt","resolvedAt"]},"description":"One page of fires, newest first."},"nextCursor":{"type":["string","null"],"description":"Pass as `cursor` to read the page after this one. Null on the last page."}},"required":["fires","nextCursor"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Trigger not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"parameters":[{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"in":"query","name":"cursor","schema":{"type":"string"},"description":"The `nextCursor` from the previous page. Omit for the newest fires."},{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]}},"/api/triggers/{id}/enable":{"post":{"operationId":"postApiTriggersByIdEnable","description":"Resume an automation. A report's schedule is put back on the calendar.","responses":{"200":{"description":"Trigger resumed","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"action":{"type":"string","enum":["SEND_EMAIL","ADD_TO_DATASET","ADD_TO_ANNOTATION_QUEUE","SEND_SLACK_MESSAGE","SEND_WEBHOOK"]},"actionParams":{"type":"object","additionalProperties":{},"description":"Where this automation delivers, with every credential value replaced by the `[redacted]` placeholder. Which channel is configured, which destination is set and which header names are in play all survive; the values never leave; a Slack automation names its connection by `slackIntegrationId` and carries no secret. Sending the placeholder back on an update keeps the stored value. The rule this automation fires by is not here — it is stated in `graphAlert` or `report`, and sending it in this field is refused."},"graphAlert":{"type":["object","null"],"properties":{"threshold":{"type":"number"},"operator":{"type":"string","enum":["gt","lt","gte","lte","eq"]},"timePeriod":{"anyOf":[{"type":"number","const":1},{"type":"number","const":5},{"type":"number","const":15},{"type":"number","const":30},{"type":"number","const":60},{"type":"number","const":1440}]},"seriesName":{"type":"string","minLength":1}},"required":["threshold","operator","timePeriod","seriesName"],"description":"The rule an alert fires by. Null for anything that is not one."},"report":{"type":["object","null"],"properties":{"source":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"dashboard"},"dashboardId":{"type":"string","minLength":1}},"required":["kind","dashboardId"]},{"type":"object","properties":{"kind":{"type":"string","const":"customGraph"},"customGraphId":{"type":"string","minLength":1}},"required":["kind","customGraphId"]},{"type":"object","properties":{"kind":{"type":"string","const":"traceQuery"},"filters":{"type":"object","additionalProperties":{},"default":{}},"metric":{"type":"string"},"topN":{"type":"integer","minimum":1,"maximum":100,"default":5}},"required":["kind","filters","topN"]}]},"schedule":{"type":"object","properties":{"cron":{"type":"string","minLength":1,"maxLength":120},"timezone":{"type":"string","minLength":1,"maxLength":64}},"required":["cron","timezone"]},"compareToPrevious":{"type":"boolean","default":false}},"required":["source","schedule","compareToPrevious"],"description":"What a report renders and when. Null for anything else."},"filters":{"type":"object","additionalProperties":{}},"filterQuery":{"type":["string","null"]},"kind":{"type":"string","enum":["AUTOMATION","ALERT","REPORT"],"description":"What this automation is about: matching traces, a metric crossing a threshold, or a schedule."},"customGraphId":{"type":["string","null"]},"notificationCadence":{"type":["string","null"]},"traceDebounceMs":{"type":["number","null"]},"templates":{"type":"object","properties":{"slackTemplateType":{"type":["string","null"],"enum":["string","block_kit",null]},"slackTemplate":{"type":["string","null"]},"emailSubjectTemplate":{"type":["string","null"]},"emailBodyTemplate":{"type":["string","null"]}},"description":"The Liquid templates this automation's message is rendered from. Absent fields render the LangWatch default for the channel."},"active":{"type":"boolean"},"message":{"type":["string","null"]},"alertType":{"type":["string","null"],"enum":["CRITICAL","WARNING","INFO",null]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"platformUrl":{"type":"string","format":"uri"}},"required":["id","name","action","actionParams","graphAlert","report","filters","filterQuery","kind","customGraphId","notificationCadence","traceDebounceMs","templates","active","message","alertType","createdAt","updatedAt","platformUrl"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Trigger not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]}},"/api/triggers/{id}/disable":{"post":{"operationId":"postApiTriggersByIdDisable","description":"Pause an automation. A report stops claiming its schedule.","responses":{"200":{"description":"Trigger paused","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"action":{"type":"string","enum":["SEND_EMAIL","ADD_TO_DATASET","ADD_TO_ANNOTATION_QUEUE","SEND_SLACK_MESSAGE","SEND_WEBHOOK"]},"actionParams":{"type":"object","additionalProperties":{},"description":"Where this automation delivers, with every credential value replaced by the `[redacted]` placeholder. Which channel is configured, which destination is set and which header names are in play all survive; the values never leave; a Slack automation names its connection by `slackIntegrationId` and carries no secret. Sending the placeholder back on an update keeps the stored value. The rule this automation fires by is not here — it is stated in `graphAlert` or `report`, and sending it in this field is refused."},"graphAlert":{"type":["object","null"],"properties":{"threshold":{"type":"number"},"operator":{"type":"string","enum":["gt","lt","gte","lte","eq"]},"timePeriod":{"anyOf":[{"type":"number","const":1},{"type":"number","const":5},{"type":"number","const":15},{"type":"number","const":30},{"type":"number","const":60},{"type":"number","const":1440}]},"seriesName":{"type":"string","minLength":1}},"required":["threshold","operator","timePeriod","seriesName"],"description":"The rule an alert fires by. Null for anything that is not one."},"report":{"type":["object","null"],"properties":{"source":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"dashboard"},"dashboardId":{"type":"string","minLength":1}},"required":["kind","dashboardId"]},{"type":"object","properties":{"kind":{"type":"string","const":"customGraph"},"customGraphId":{"type":"string","minLength":1}},"required":["kind","customGraphId"]},{"type":"object","properties":{"kind":{"type":"string","const":"traceQuery"},"filters":{"type":"object","additionalProperties":{},"default":{}},"metric":{"type":"string"},"topN":{"type":"integer","minimum":1,"maximum":100,"default":5}},"required":["kind","filters","topN"]}]},"schedule":{"type":"object","properties":{"cron":{"type":"string","minLength":1,"maxLength":120},"timezone":{"type":"string","minLength":1,"maxLength":64}},"required":["cron","timezone"]},"compareToPrevious":{"type":"boolean","default":false}},"required":["source","schedule","compareToPrevious"],"description":"What a report renders and when. Null for anything else."},"filters":{"type":"object","additionalProperties":{}},"filterQuery":{"type":["string","null"]},"kind":{"type":"string","enum":["AUTOMATION","ALERT","REPORT"],"description":"What this automation is about: matching traces, a metric crossing a threshold, or a schedule."},"customGraphId":{"type":["string","null"]},"notificationCadence":{"type":["string","null"]},"traceDebounceMs":{"type":["number","null"]},"templates":{"type":"object","properties":{"slackTemplateType":{"type":["string","null"],"enum":["string","block_kit",null]},"slackTemplate":{"type":["string","null"]},"emailSubjectTemplate":{"type":["string","null"]},"emailBodyTemplate":{"type":["string","null"]}},"description":"The Liquid templates this automation's message is rendered from. Absent fields render the LangWatch default for the channel."},"active":{"type":"boolean"},"message":{"type":["string","null"]},"alertType":{"type":["string","null"],"enum":["CRITICAL","WARNING","INFO",null]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"platformUrl":{"type":"string","format":"uri"}},"required":["id","name","action","actionParams","graphAlert","report","filters","filterQuery","kind","customGraphId","notificationCadence","traceDebounceMs","templates","active","message","alertType","createdAt","updatedAt","platformUrl"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Trigger not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]}},"/api/triggers/{id}/test-fire":{"post":{"operationId":"postApiTriggersByIdTestFire","description":"Send this automation's message to the destination it is configured with, so you can confirm it arrives. Nothing is recorded as a fire.","responses":{"200":{"description":"Test fire sent","content":{"application/json":{"schema":{"type":"object","properties":{"channel":{"type":"string","enum":["email","slack","webhook"]},"recipientCount":{"type":"number"},"usedDefault":{"type":"boolean","description":"Whether the LangWatch default message was rendered because this automation states no template of its own."},"missingVariables":{"type":"array","items":{"type":"string"}},"errors":{"type":"array","items":{"type":"string"}},"httpStatus":{"type":"number","description":"Webhook only: what the endpoint answered with."}},"required":["channel","recipientCount","usedDefault","missingVariables","errors"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Trigger not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]}},"/api/slack-connections":{"get":{"operationId":"getApiSlackConnections","description":"List the Slack connections this project can deliver through: its own and its organization's, by name. Never returns a token or webhook URL.","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"What an automation's `slackIntegrationId` names to post through this connection."},"name":{"type":"string"},"kind":{"type":"string","enum":["bot","webhook"],"description":"`bot` posts as the LangWatch Slack app and needs a `slackChannelId` on the automation; `webhook` posts to its incoming webhook's channel."},"scopeType":{"type":"string","enum":["ORGANIZATION","PROJECT"]},"scopeId":{"type":"string"},"scopeName":{"type":"string"},"slackTeamName":{"type":["string","null"],"description":"The Slack workspace a bot connection posts into."},"createdAt":{"type":"string"}},"required":["id","name","kind","scopeType","scopeId","scopeName","slackTeamName","createdAt"]}}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"security":[{"project_api_key":[]}]}},"/api/webhooks/v1/endpoints":{"post":{"operationId":"postApiWebhooksV1Endpoints","tags":["Webhooks"],"summary":"Create a webhook endpoint","description":"Create a webhook endpoint. Name one destination: `url` for `destination_kind: http`, `sqs` for `destination_kind: sqs`. Naming the other kind's field is a 400 that says which field does not belong, rather than a 201 that saved half the body. `destination_kind` may be omitted and then means `http`. The signing secret is returned ONCE in this response and never again; roll it to get a new one. Send `Idempotency-Key` to make a retry safe: a replay returns the original response including its `secret`, which is the only way to recover a secret whose response was lost in transit.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"A caller-chosen key, 8 to 255 characters, that makes this create safe to retry. The first request to use a key runs normally and its response is stored for 24 hours. A later request with the same key and the same body is not executed again: it returns the stored response, marked with `X-Idempotent-Replay: true`. The same key with a different body is refused 409 `idempotency_error`, as is a retry sent while the original is still running. Only successful responses are stored, so a create that failed can simply be retried with the same key.","schema":{"type":"string","minLength":8,"maxLength":255}}],"responses":{"201":{"description":"The endpoint, with the signing secret this body alone carries","headers":{"X-Idempotent-Replay":{"description":"Present and `true` only when this body came from a stored response rather than a fresh execution. Absent on the first use of a key, and on every request that carries no key.","schema":{"type":"string","enum":["true"]}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"oneOf":[{"type":"object","properties":{"destination_kind":{"type":"string","const":"http"},"url":{"type":"string"},"sqs":{"type":"null"},"id":{"type":"string"},"enabled_events":{"type":"array","items":{"type":"string"}},"status":{"type":"string","enum":["active","disabled"]},"disabled_reason":{"type":["string","null"]},"disabled_at":{"type":["string","null"]},"failing_since":{"type":["string","null"]},"last_success_at":{"type":["string","null"]},"last_failure_at":{"type":["string","null"]},"max_batch_size":{"type":"integer"},"max_batch_delay_ms":{"type":"integer"},"max_in_flight":{"type":"integer"},"created_at":{"type":"string"},"updated_at":{"type":"string"},"secret":{"type":"string"}},"required":["destination_kind","url","sqs","id","enabled_events","status","disabled_reason","disabled_at","failing_since","last_success_at","last_failure_at","max_batch_size","max_batch_delay_ms","max_in_flight","created_at","updated_at","secret"]},{"type":"object","properties":{"destination_kind":{"type":"string","const":"sqs"},"url":{"type":"null"},"sqs":{"type":"object","properties":{"queue_url":{"type":"string"},"region":{"type":"string"},"account_id":{"type":"string"},"queue_name":{"type":"string"},"credential_mode":{"type":"string","enum":["assume_role","static","ambient"]},"role_arn":{"type":["string","null"]},"external_id":{"type":["string","null"]},"access_key_id":{"type":["string","null"]}},"required":["queue_url","region","account_id","queue_name","credential_mode","role_arn","external_id","access_key_id"]},"id":{"type":"string"},"enabled_events":{"type":"array","items":{"type":"string"}},"status":{"type":"string","enum":["active","disabled"]},"disabled_reason":{"type":["string","null"]},"disabled_at":{"type":["string","null"]},"failing_since":{"type":["string","null"]},"last_success_at":{"type":["string","null"]},"last_failure_at":{"type":["string","null"]},"max_batch_size":{"type":"integer"},"max_batch_delay_ms":{"type":"integer"},"max_in_flight":{"type":"integer"},"created_at":{"type":"string"},"updated_at":{"type":"string"},"secret":{"type":"string"}},"required":["destination_kind","url","sqs","id","enabled_events","status","disabled_reason","disabled_at","failing_since","last_success_at","last_failure_at","max_batch_size","max_batch_delay_ms","max_in_flight","created_at","updated_at","secret"]}]}},"required":["data"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"destination_kind":{"type":"string","enum":["http","sqs"]},"url":{"type":"string","minLength":1,"maxLength":2000},"sqs":{"type":"object","properties":{"queue_url":{"type":"string","minLength":1,"maxLength":2000},"role_arn":{"type":"string","minLength":1,"maxLength":2048},"external_id":{"type":"string","minLength":1,"maxLength":1224},"access_key_id":{"type":"string","minLength":1,"maxLength":128},"secret_access_key":{"type":"string","minLength":1,"maxLength":256}},"required":["queue_url"]},"enabled_events":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"minItems":1,"maxItems":100},"max_batch_size":{"type":"integer"},"max_batch_delay_ms":{"type":"integer"},"max_in_flight":{"type":"integer"}},"required":["enabled_events"]}}}},"security":[{"admin_api_key":[]}]},"get":{"operationId":"getApiWebhooksV1Endpoints","tags":["Webhooks"],"summary":"List webhook endpoints","description":"List the organization's webhook endpoints","responses":{"200":{"description":"Every endpoint the organization has, archived ones excluded","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"destination_kind":{"type":"string","const":"http"},"url":{"type":"string"},"sqs":{"type":"null"},"id":{"type":"string"},"enabled_events":{"type":"array","items":{"type":"string"}},"status":{"type":"string","enum":["active","disabled"]},"disabled_reason":{"type":["string","null"]},"disabled_at":{"type":["string","null"]},"failing_since":{"type":["string","null"]},"last_success_at":{"type":["string","null"]},"last_failure_at":{"type":["string","null"]},"max_batch_size":{"type":"integer"},"max_batch_delay_ms":{"type":"integer"},"max_in_flight":{"type":"integer"},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["destination_kind","url","sqs","id","enabled_events","status","disabled_reason","disabled_at","failing_since","last_success_at","last_failure_at","max_batch_size","max_batch_delay_ms","max_in_flight","created_at","updated_at"]},{"type":"object","properties":{"destination_kind":{"type":"string","const":"sqs"},"url":{"type":"null"},"sqs":{"type":"object","properties":{"queue_url":{"type":"string"},"region":{"type":"string"},"account_id":{"type":"string"},"queue_name":{"type":"string"},"credential_mode":{"type":"string","enum":["assume_role","static","ambient"]},"role_arn":{"type":["string","null"]},"external_id":{"type":["string","null"]},"access_key_id":{"type":["string","null"]}},"required":["queue_url","region","account_id","queue_name","credential_mode","role_arn","external_id","access_key_id"]},"id":{"type":"string"},"enabled_events":{"type":"array","items":{"type":"string"}},"status":{"type":"string","enum":["active","disabled"]},"disabled_reason":{"type":["string","null"]},"disabled_at":{"type":["string","null"]},"failing_since":{"type":["string","null"]},"last_success_at":{"type":["string","null"]},"last_failure_at":{"type":["string","null"]},"max_batch_size":{"type":"integer"},"max_batch_delay_ms":{"type":"integer"},"max_in_flight":{"type":"integer"},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["destination_kind","url","sqs","id","enabled_events","status","disabled_reason","disabled_at","failing_since","last_success_at","last_failure_at","max_batch_size","max_batch_delay_ms","max_in_flight","created_at","updated_at"]}]}}},"required":["data"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"security":[{"admin_api_key":[]}]}},"/api/webhooks/v1/endpoints/{id}":{"get":{"operationId":"getApiWebhooksV1EndpointsById","tags":["Webhooks"],"summary":"Get a webhook endpoint","description":"Get one webhook endpoint","responses":{"200":{"description":"The endpoint","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"oneOf":[{"type":"object","properties":{"destination_kind":{"type":"string","const":"http"},"url":{"type":"string"},"sqs":{"type":"null"},"id":{"type":"string"},"enabled_events":{"type":"array","items":{"type":"string"}},"status":{"type":"string","enum":["active","disabled"]},"disabled_reason":{"type":["string","null"]},"disabled_at":{"type":["string","null"]},"failing_since":{"type":["string","null"]},"last_success_at":{"type":["string","null"]},"last_failure_at":{"type":["string","null"]},"max_batch_size":{"type":"integer"},"max_batch_delay_ms":{"type":"integer"},"max_in_flight":{"type":"integer"},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["destination_kind","url","sqs","id","enabled_events","status","disabled_reason","disabled_at","failing_since","last_success_at","last_failure_at","max_batch_size","max_batch_delay_ms","max_in_flight","created_at","updated_at"]},{"type":"object","properties":{"destination_kind":{"type":"string","const":"sqs"},"url":{"type":"null"},"sqs":{"type":"object","properties":{"queue_url":{"type":"string"},"region":{"type":"string"},"account_id":{"type":"string"},"queue_name":{"type":"string"},"credential_mode":{"type":"string","enum":["assume_role","static","ambient"]},"role_arn":{"type":["string","null"]},"external_id":{"type":["string","null"]},"access_key_id":{"type":["string","null"]}},"required":["queue_url","region","account_id","queue_name","credential_mode","role_arn","external_id","access_key_id"]},"id":{"type":"string"},"enabled_events":{"type":"array","items":{"type":"string"}},"status":{"type":"string","enum":["active","disabled"]},"disabled_reason":{"type":["string","null"]},"disabled_at":{"type":["string","null"]},"failing_since":{"type":["string","null"]},"last_success_at":{"type":["string","null"]},"last_failure_at":{"type":["string","null"]},"max_batch_size":{"type":"integer"},"max_batch_delay_ms":{"type":"integer"},"max_in_flight":{"type":"integer"},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["destination_kind","url","sqs","id","enabled_events","status","disabled_reason","disabled_at","failing_since","last_success_at","last_failure_at","max_batch_size","max_batch_delay_ms","max_in_flight","created_at","updated_at"]}]}},"required":["data"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"admin_api_key":[]}]},"patch":{"operationId":"patchApiWebhooksV1EndpointsById","tags":["Webhooks"],"summary":"Update a webhook endpoint","description":"Update a webhook endpoint's address, event subscriptions, or status (`active` re-enables, `disabled` pauses; re-enabling does not re-send the gap, replay covers it). `destination_kind` cannot change: batches already planned against the old transport are in flight, so a move means a new endpoint alongside this one until it has drained.","responses":{"200":{"description":"The endpoint as it now stands","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"oneOf":[{"type":"object","properties":{"destination_kind":{"type":"string","const":"http"},"url":{"type":"string"},"sqs":{"type":"null"},"id":{"type":"string"},"enabled_events":{"type":"array","items":{"type":"string"}},"status":{"type":"string","enum":["active","disabled"]},"disabled_reason":{"type":["string","null"]},"disabled_at":{"type":["string","null"]},"failing_since":{"type":["string","null"]},"last_success_at":{"type":["string","null"]},"last_failure_at":{"type":["string","null"]},"max_batch_size":{"type":"integer"},"max_batch_delay_ms":{"type":"integer"},"max_in_flight":{"type":"integer"},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["destination_kind","url","sqs","id","enabled_events","status","disabled_reason","disabled_at","failing_since","last_success_at","last_failure_at","max_batch_size","max_batch_delay_ms","max_in_flight","created_at","updated_at"]},{"type":"object","properties":{"destination_kind":{"type":"string","const":"sqs"},"url":{"type":"null"},"sqs":{"type":"object","properties":{"queue_url":{"type":"string"},"region":{"type":"string"},"account_id":{"type":"string"},"queue_name":{"type":"string"},"credential_mode":{"type":"string","enum":["assume_role","static","ambient"]},"role_arn":{"type":["string","null"]},"external_id":{"type":["string","null"]},"access_key_id":{"type":["string","null"]}},"required":["queue_url","region","account_id","queue_name","credential_mode","role_arn","external_id","access_key_id"]},"id":{"type":"string"},"enabled_events":{"type":"array","items":{"type":"string"}},"status":{"type":"string","enum":["active","disabled"]},"disabled_reason":{"type":["string","null"]},"disabled_at":{"type":["string","null"]},"failing_since":{"type":["string","null"]},"last_success_at":{"type":["string","null"]},"last_failure_at":{"type":["string","null"]},"max_batch_size":{"type":"integer"},"max_batch_delay_ms":{"type":"integer"},"max_in_flight":{"type":"integer"},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["destination_kind","url","sqs","id","enabled_events","status","disabled_reason","disabled_at","failing_since","last_success_at","last_failure_at","max_batch_size","max_batch_delay_ms","max_in_flight","created_at","updated_at"]}]}},"required":["data"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"destination_kind":{"type":"string","enum":["http","sqs"]},"url":{"type":"string","minLength":1,"maxLength":2000},"sqs":{"type":"object","properties":{"queue_url":{"type":"string","minLength":1,"maxLength":2000},"role_arn":{"type":"string","minLength":1,"maxLength":2048},"external_id":{"type":"string","minLength":1,"maxLength":1224},"access_key_id":{"type":"string","minLength":1,"maxLength":128},"secret_access_key":{"type":"string","minLength":1,"maxLength":256}}},"enabled_events":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"minItems":1,"maxItems":100},"status":{"type":"string","enum":["active","disabled"]},"max_batch_size":{"type":"integer"},"max_batch_delay_ms":{"type":"integer"},"max_in_flight":{"type":"integer"}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"admin_api_key":[]}]},"delete":{"operationId":"deleteApiWebhooksV1EndpointsById","tags":["Webhooks"],"summary":"Archive a webhook endpoint","description":"Archive a webhook endpoint","responses":{"200":{"description":"Archived: the endpoint is gone from every read and delivers nothing","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"archived":{"type":"boolean","const":true}},"required":["archived"]}},"required":["data"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"admin_api_key":[]}]}},"/api/webhooks/v1/endpoints/{id}/roll-secret":{"post":{"operationId":"postApiWebhooksV1EndpointsByIdRollSecret","tags":["Webhooks"],"summary":"Roll an endpoint's signing secret","description":"Roll the endpoint's signing secret. The new secret is returned ONCE; deliveries sign with it immediately.","responses":{"200":{"description":"The endpoint, with the new signing secret this body alone carries","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"oneOf":[{"type":"object","properties":{"destination_kind":{"type":"string","const":"http"},"url":{"type":"string"},"sqs":{"type":"null"},"id":{"type":"string"},"enabled_events":{"type":"array","items":{"type":"string"}},"status":{"type":"string","enum":["active","disabled"]},"disabled_reason":{"type":["string","null"]},"disabled_at":{"type":["string","null"]},"failing_since":{"type":["string","null"]},"last_success_at":{"type":["string","null"]},"last_failure_at":{"type":["string","null"]},"max_batch_size":{"type":"integer"},"max_batch_delay_ms":{"type":"integer"},"max_in_flight":{"type":"integer"},"created_at":{"type":"string"},"updated_at":{"type":"string"},"secret":{"type":"string"}},"required":["destination_kind","url","sqs","id","enabled_events","status","disabled_reason","disabled_at","failing_since","last_success_at","last_failure_at","max_batch_size","max_batch_delay_ms","max_in_flight","created_at","updated_at","secret"]},{"type":"object","properties":{"destination_kind":{"type":"string","const":"sqs"},"url":{"type":"null"},"sqs":{"type":"object","properties":{"queue_url":{"type":"string"},"region":{"type":"string"},"account_id":{"type":"string"},"queue_name":{"type":"string"},"credential_mode":{"type":"string","enum":["assume_role","static","ambient"]},"role_arn":{"type":["string","null"]},"external_id":{"type":["string","null"]},"access_key_id":{"type":["string","null"]}},"required":["queue_url","region","account_id","queue_name","credential_mode","role_arn","external_id","access_key_id"]},"id":{"type":"string"},"enabled_events":{"type":"array","items":{"type":"string"}},"status":{"type":"string","enum":["active","disabled"]},"disabled_reason":{"type":["string","null"]},"disabled_at":{"type":["string","null"]},"failing_since":{"type":["string","null"]},"last_success_at":{"type":["string","null"]},"last_failure_at":{"type":["string","null"]},"max_batch_size":{"type":"integer"},"max_batch_delay_ms":{"type":"integer"},"max_in_flight":{"type":"integer"},"created_at":{"type":"string"},"updated_at":{"type":"string"},"secret":{"type":"string"}},"required":["destination_kind","url","sqs","id","enabled_events","status","disabled_reason","disabled_at","failing_since","last_success_at","last_failure_at","max_batch_size","max_batch_delay_ms","max_in_flight","created_at","updated_at","secret"]}]}},"required":["data"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"admin_api_key":[]}]}},"/api/webhooks/v1/endpoints/{id}/test":{"post":{"operationId":"postApiWebhooksV1EndpointsByIdTest","tags":["Webhooks"],"summary":"Send a test event to an endpoint","description":"Send a signed test event through the full delivery path. Contract: the route answers 200 whenever the test itself ran; data.delivered says whether the receiver accepted it, so clients must read the body, not the status code.","responses":{"200":{"description":"The test ran; `data.delivered` carries the receiver's verdict","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"delivered":{"type":"boolean"},"response_status":{"type":["integer","null"]},"response_body":{"type":"string"},"error":{"type":"string"}},"required":["delivered","response_status"]}},"required":["data"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"admin_api_key":[]}]}},"/api/webhooks/v1/endpoints/{id}/deliveries":{"get":{"operationId":"getApiWebhooksV1EndpointsByIdDeliveries","tags":["Webhooks"],"summary":"List an endpoint's delivery attempts","description":"The endpoint's delivery log: every attempt with the receiver's HTTP status, latency, and error","responses":{"200":{"description":"One page of delivery attempts, newest first","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"dispatch_id":{"type":"string"},"attempt":{"type":"integer"},"event_count":{"type":"integer"},"outcome":{"type":"string","enum":["success","retryable","terminal","pending"]},"response_status":{"type":["integer","null"]},"latency_ms":{"type":["integer","null"]},"error":{"type":["string","null"]},"fired_at":{"type":"string"}},"required":["id","dispatch_id","attempt","event_count","outcome","response_status","latency_ms","error","fired_at"]}},"next_cursor":{"type":["string","null"],"description":"Pass back as `cursor` for the next page. Null means the walk is exhausted; a full page does NOT mean there is more."}},"required":["data","next_cursor"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"parameters":[{"in":"query","name":"cursor","schema":{"type":"string","maxLength":500}},{"in":"query","name":"limit","schema":{"type":"integer","exclusiveMinimum":0,"maximum":200,"default":50}},{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"admin_api_key":[]}]}},"/api/webhooks/v1/endpoints/{id}/health":{"get":{"operationId":"getApiWebhooksV1EndpointsByIdHealth","tags":["Webhooks"],"summary":"Read an endpoint's delivery health","description":"Delivery health. The headline number is oldest_undelivered_age_ms, the feed's staleness: age of the oldest envelope still buffered or retrying. Also: DLQ depth, failure streak, sends/min, success rate, and p95 latency over the last hour.","responses":{"200":{"description":"The endpoint's delivery health","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"status":{"type":"string","enum":["active","disabled"]},"disabled_reason":{"type":["string","null"]},"failing_since":{"type":["string","null"]},"last_success_at":{"type":["string","null"]},"last_failure_at":{"type":["string","null"]},"oldest_undelivered_age_ms":{"type":["integer","null"]},"dlq_depth":{"type":"integer"},"sends_per_minute":{"type":"number"},"success_rate":{"type":["number","null"]},"p95_latency_ms":{"type":["integer","null"]}},"required":["status","disabled_reason","failing_since","last_success_at","last_failure_at","oldest_undelivered_age_ms","dlq_depth","sends_per_minute","success_rate","p95_latency_ms"]}},"required":["data"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"admin_api_key":[]}]}},"/api/webhooks/v1/event-types":{"get":{"operationId":"getApiWebhooksV1EventTypes","tags":["Webhooks"],"summary":"List subscribable event types","description":"The event catalog: every subscribable type, grouped by family; types marked emitting=false are declared contracts whose producers have not shipped yet","responses":{"200":{"description":"Every subscribable event type","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string"},"family":{"type":"string"},"schema_version":{"type":"string"},"is_emitting":{"type":"boolean"},"description":{"type":"string"}},"required":["type","family","schema_version","is_emitting","description"]}}},"required":["data"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"security":[{"admin_api_key":[]}]}},"/api/webhooks/v1/events":{"get":{"operationId":"getApiWebhooksV1Events","tags":["Webhooks"],"summary":"List emitted events","description":"The organization's emitted-events log for the request families: cursor-paged, newest first, filter by type. `from` and `to` bound the created range in epoch milliseconds, are REQUIRED, and `from` must not be later than `to` — a range that ends before it starts is rejected rather than answered with an empty page. They are required because the log is a ranged read over the 13-month spend table and an unbounded walk sorts all of it on every page. Webhooks are push over this log, never the only copy of it. SERVES `gateway.request.completed` and `gateway.request.settled` ONLY. The governance families (`gateway.budget.*`, `gateway.virtual_key.*`) are delivered by webhook but are not retained in a queryable log, so they cannot be listed or replayed here; any other type returns an empty page rather than an error, so a client can probe forward-compatibly.","responses":{"200":{"description":"One page of emitted-event envelopes, newest first","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string"},"created":{"type":"string"},"schema_version":{"type":"string"},"data":{"type":"object","additionalProperties":{}}},"required":["id","type","created","schema_version","data"]}},"next_cursor":{"type":["string","null"],"description":"Pass back as `cursor` for the next page. Null means the walk is exhausted; a full page does NOT mean there is more."}},"required":["data","next_cursor"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"parameters":[{"in":"query","name":"type","schema":{"type":"string","minLength":1,"maxLength":200}},{"in":"query","name":"from","schema":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"required":true},{"in":"query","name":"to","schema":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"required":true},{"in":"query","name":"cursor","schema":{"type":"string","maxLength":500}},{"in":"query","name":"limit","schema":{"type":"integer","exclusiveMinimum":0,"maximum":200,"default":50}}],"security":[{"admin_api_key":[]}]}},"/api/webhooks/v1/events/{id}":{"get":{"operationId":"getApiWebhooksV1EventsById","tags":["Webhooks"],"summary":"Get one emitted event","description":"One emitted event by its id, as it was delivered. Serves the same families the events log serves. A 404 covers every reason the log cannot answer -- never emitted, past the retention horizon, or belonging to another organization -- because telling those apart would confirm the existence of another tenant's request ids.","responses":{"200":{"description":"The envelope, exactly as it was delivered","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string"},"created":{"type":"string"},"schema_version":{"type":"string"},"data":{"type":"object","additionalProperties":{}}},"required":["id","type","created","schema_version","data"]}},"required":["data"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"admin_api_key":[]}]}},"/api/gateway/v1/spend-summaries":{"get":{"operationId":"getApiGatewayV1SpendSummaries","responses":{"200":{"description":"Per-key spend rollups","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"group":{"type":"object","additionalProperties":{"type":"string"}},"bucket_start":{"type":["string","null"]},"event_count":{"type":"integer"},"settled_count":{"type":"integer"},"usage":{"type":"object","properties":{"input_tokens":{"type":"integer"},"output_tokens":{"type":"integer"},"cache_read_input_tokens":{"type":"integer"},"cache_creation_input_tokens":{"type":"integer"},"reasoning_tokens":{"type":"integer"},"input_image_tokens":{"type":"integer","description":"Image tokens billed on the input side, 0 when the request carried no image. Priced at its own rate and disjoint from input_tokens, which never includes it."},"output_image_tokens":{"type":"integer","description":"Image tokens the answer was billed for, 0 when the answer held no image. Priced at its own rate and disjoint from output_tokens: an image_generation row reports output_tokens 0 and its render here, so a reconciler reading output_tokens alone sees none of the image traffic."},"image_count":{"type":"integer","description":"Images the request carried, 0 when it carried none. Display only: no rate prices it, so it never belongs in a cost sum."}},"required":["input_tokens","output_tokens","cache_read_input_tokens","cache_creation_input_tokens","reasoning_tokens","input_image_tokens","output_image_tokens","image_count"]},"cost":{"type":"object","properties":{"total_usd":{"type":"string","description":"Display value. Decimal string, up to 9 fractional digits, trailing zeros trimmed, never exponent notation. Use nano_usd for arithmetic."},"nano_usd":{"type":"integer","description":"Canonical integer cost, nano-USD. Rated as an integer and summed as one, so this is the figure to reconcile against."}},"required":["total_usd","nano_usd"]}},"required":["key","group","bucket_start","event_count","settled_count","usage","cost"]}},"next_cursor":{"type":["string","null"]}},"required":["data","next_cursor"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"tags":["Gateway Spend"],"summary":"List spend summaries","description":"Reconciliation checksum fast path: spend rollups with token classes and integer nano-USD cost. Settled (unpriced) requests are counted separately as settled_count and never included in cost sums. Diff individual items via /spend-events only when a checksum diverges. `group_by` takes one or two of virtual_key, end_user, project, model, provider, principal and request_type, comma-separated, and `bucket` adds an hour or day column in the `timezone` you name. `key` stays the first dimension's value for consumers written against the single-dimension surface; read `group` to tell two dimensions apart. Paged by group key ascending: follow next_cursor until it comes back null, because a page that is full does not mean the window held nothing more. Grouping by model or provider, or into time buckets, is refused with `gateway_spend_group_by_unstable` while the window is recent enough that outcomes can still arrive, because those groups can move under a page walk and the totals would double-count some requests and miss others; ask for an older range, or send `allow_unstable` when an approximate shape is enough. Every filter here is accepted by /spend-events too, and the reverse holds apart from `status=admitted`: a rollup sums the cost of requests past admission, so an admitted request has none to contribute and that narrowing is refused rather than answered with a zero. Ask /spend-events for those.","parameters":[{"in":"query","name":"group_by","schema":{"type":"string","example":"model,end_user"},"required":true,"description":"One or two dimensions, comma separated: virtual_key, end_user, project, model, provider, principal, request_type. A dimension may not repeat. Each row's `key` is the first dimension's value and `group` names them all, so two rows may share a key."},{"in":"query","name":"bucket","schema":{"type":"string","enum":["none","hour","day"],"default":"none"}},{"in":"query","name":"timezone","schema":{"type":"string","minLength":1,"maxLength":64,"default":"UTC"}},{"in":"query","name":"allow_unstable","schema":{"type":"string","default":"false","example":"true"},"description":"true, 1, yes for yes; false, 0, no or omitted for no. Case does not matter, so a Python True is accepted as sent."},{"in":"query","name":"from","schema":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991,"example":1782864000000},"required":true,"description":"Milliseconds since the Unix epoch, not seconds. An epoch in seconds is a valid integer here and answers for 1970, so a mismatched unit reads as an empty window rather than as an error."},{"in":"query","name":"to","schema":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991,"example":1782864000000},"required":true,"description":"Milliseconds since the Unix epoch, not seconds. An epoch in seconds is a valid integer here and answers for 1970, so a mismatched unit reads as an empty window rather than as an error."},{"in":"query","name":"cursor","schema":{"type":"string","maxLength":500}},{"in":"query","name":"limit","schema":{"type":"integer","exclusiveMinimum":0,"maximum":1000,"default":500}},{"in":"query","name":"project_id","schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":100},{"type":"array","items":{"type":"string","minLength":1,"maxLength":100},"maxItems":100}]}},{"in":"query","name":"team_id","schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":100},{"type":"array","items":{"type":"string","minLength":1,"maxLength":100},"maxItems":100}]}},{"in":"query","name":"external_id","schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":200},{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":100}]}},{"in":"query","name":"virtual_key_id","schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":100},{"type":"array","items":{"type":"string","minLength":1,"maxLength":100},"maxItems":100}]}},{"in":"query","name":"end_user_id","schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":256},{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"maxItems":100}]}},{"in":"query","name":"principal_user_id","schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":100},{"type":"array","items":{"type":"string","minLength":1,"maxLength":100},"maxItems":100}]}},{"in":"query","name":"model","schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":200},{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":100}]}},{"in":"query","name":"provider_key","schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":100},{"type":"array","items":{"type":"string","minLength":1,"maxLength":100},"maxItems":100}]}},{"in":"query","name":"request_type","schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":50},{"type":"array","items":{"type":"string","minLength":1,"maxLength":50},"maxItems":100}]}},{"in":"query","name":"label","schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":200},{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":100}]}},{"in":"query","name":"metadata","schema":{"anyOf":[{"type":"string","minLength":3,"maxLength":640},{"type":"array","items":{"type":"string","minLength":3,"maxLength":640},"maxItems":100}]}},{"in":"query","name":"status","schema":{"type":"string","enum":["success","error","confirmed","failed","settled"]},"description":"Narrow to one lifecycle status. `admitted` is not accepted here: a rollup sums the cost of requests past admission, and an admitted request is still in flight with no cost of its own yet. Ask /spend-events for those."}],"security":[{"admin_api_key":[]}]}},"/api/gateway/v1/spend-events":{"get":{"operationId":"getApiGatewayV1SpendEvents","tags":["Gateway Spend"],"summary":"List spend events","description":"Cursor-paged pull over the per-request spend record, ascending by insert order so rows folded late are never skipped by an in-flight cursor. Events are the same canonical objects webhook deliveries carry. Retention is a fixed 13 months, which bounds reconciliation and replay. When feeding a downstream biller, mind its dedup window (Metronome 34 days and Stripe meters 24h+ at the time of writing; both vendors own those numbers, so confirm the current one before you rely on it): re-pulling older ranges into a biller past its window can double-bill. Every filter here is accepted by /spend-summaries too, so a checksum that disagrees can be diffed on exactly the same narrowing; the one difference is `status=admitted`, which only this read answers, because an admitted request is still in flight and contributes no cost to a rollup. Repeat a filter to widen it (`model=a&model=b` matches either); name two different filters to narrow. `metadata` is written `key:value`, split on the first colon, and repeating a key widens that key. `team_id` and `external_id` name Postgres records and are resolved to the projects and keys they cover, so a team with no projects or an external id nobody minted answers with no spend rather than with everything.","responses":{"200":{"description":"One page of billing envelopes","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string"},"created":{"type":"string"},"schema_version":{"type":"string"},"data":{"type":"object","properties":{"event_id":{"type":"string"},"event_type":{"type":"string"},"gateway_request_id":{"type":"string"},"occurred_at":{"type":"string"},"usage":{"type":["object","null"],"properties":{"input_tokens":{"type":"integer"},"output_tokens":{"type":"integer"},"cache_read_input_tokens":{"type":"integer"},"cache_creation_input_tokens":{"type":"integer"},"reasoning_tokens":{"type":"integer"},"input_image_tokens":{"type":"integer","description":"Image tokens billed on the input side, 0 when the request carried no image. Priced at its own rate and disjoint from input_tokens, which never includes it."},"output_image_tokens":{"type":"integer","description":"Image tokens the answer was billed for, 0 when the answer held no image. Priced at its own rate and disjoint from output_tokens: an image_generation row reports output_tokens 0 and its render here, so a reconciler reading output_tokens alone sees none of the image traffic."},"image_count":{"type":"integer","description":"Images the request carried, 0 when it carried none. Display only: no rate prices it, so it never belongs in a cost sum."}},"required":["input_tokens","output_tokens","cache_read_input_tokens","cache_creation_input_tokens","reasoning_tokens","input_image_tokens","output_image_tokens","image_count"]},"cost":{"type":["object","null"],"properties":{"total_usd":{"type":"string","description":"Display value. Decimal string, up to 9 fractional digits, trailing zeros trimmed, never exponent notation. Use nano_usd for arithmetic."},"nano_usd":{"type":"integer","description":"Canonical integer cost, nano-USD. Rated as an integer and summed as one, so this is the figure to reconcile against."}},"required":["total_usd","nano_usd"]},"status":{"type":"string"},"needs_reconciliation":{"type":["boolean","null"]},"settle_reason":{"type":["string","null"]},"error":{"type":["object","null"],"properties":{"class":{"type":"string"},"http_status":{"type":["integer","null"]}},"required":["class","http_status"]},"duration_ms":{"type":["integer","null"]},"labels":{"type":"array","items":{"type":"string"}},"metadata":{"type":"object","additionalProperties":{}}},"required":["event_id","event_type","gateway_request_id","occurred_at","usage","cost","status","needs_reconciliation","settle_reason","error","duration_ms","labels","metadata"],"additionalProperties":true}},"required":["id","type","created","schema_version","data"]}},"next_cursor":{"type":["string","null"]}},"required":["data","next_cursor"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"parameters":[{"in":"query","name":"from","schema":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991,"example":1782864000000},"required":true,"description":"Milliseconds since the Unix epoch, not seconds. An epoch in seconds is a valid integer here and answers for 1970, so a mismatched unit reads as an empty window rather than as an error."},{"in":"query","name":"to","schema":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991,"example":1782864000000},"required":true,"description":"Milliseconds since the Unix epoch, not seconds. An epoch in seconds is a valid integer here and answers for 1970, so a mismatched unit reads as an empty window rather than as an error."},{"in":"query","name":"cursor","schema":{"type":"string","maxLength":500}},{"in":"query","name":"limit","schema":{"type":"integer","exclusiveMinimum":0,"maximum":200,"default":50}},{"in":"query","name":"project_id","schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":100},{"type":"array","items":{"type":"string","minLength":1,"maxLength":100},"maxItems":100}]}},{"in":"query","name":"team_id","schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":100},{"type":"array","items":{"type":"string","minLength":1,"maxLength":100},"maxItems":100}]}},{"in":"query","name":"external_id","schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":200},{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":100}]}},{"in":"query","name":"virtual_key_id","schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":100},{"type":"array","items":{"type":"string","minLength":1,"maxLength":100},"maxItems":100}]}},{"in":"query","name":"end_user_id","schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":256},{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"maxItems":100}]}},{"in":"query","name":"principal_user_id","schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":100},{"type":"array","items":{"type":"string","minLength":1,"maxLength":100},"maxItems":100}]}},{"in":"query","name":"model","schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":200},{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":100}]}},{"in":"query","name":"provider_key","schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":100},{"type":"array","items":{"type":"string","minLength":1,"maxLength":100},"maxItems":100}]}},{"in":"query","name":"request_type","schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":50},{"type":"array","items":{"type":"string","minLength":1,"maxLength":50},"maxItems":100}]}},{"in":"query","name":"label","schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":200},{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":100}]}},{"in":"query","name":"metadata","schema":{"anyOf":[{"type":"string","minLength":3,"maxLength":640},{"type":"array","items":{"type":"string","minLength":3,"maxLength":640},"maxItems":100}]}},{"in":"query","name":"status","schema":{"type":"string","enum":["success","error","admitted","confirmed","failed","settled"]}}],"security":[{"admin_api_key":[]}]}},"/api/gateway/v1/end-users/{id}/spend":{"get":{"operationId":"getApiGatewayV1EndUsersByIdSpend","tags":["Gateway Spend"],"summary":"Read one end user's spend","description":"Windowed spend rollup for one external end user across the organization (the /customer/info-style read a rebilling integration polls). `caps` lists every attributed-user budget that applies to this end user, each with its limit and the spend against it. It is an empty array until such a budget template applies, never null.","responses":{"200":{"description":"Spend and standing for one end user","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"end_user_id":{"type":"string"},"window":{"type":"string"},"from":{"type":"string"},"to":{"type":"string"},"cost":{"type":"object","properties":{"total_usd":{"type":"string","description":"Display value. Decimal string, up to 9 fractional digits, trailing zeros trimmed, never exponent notation. Use nano_usd for arithmetic."},"nano_usd":{"type":"integer","description":"Canonical integer cost, nano-USD. Rated as an integer and summed as one, so this is the figure to reconcile against."}},"required":["total_usd","nano_usd"]},"request_count":{"type":"integer"},"usage":{"type":"object","properties":{"input_tokens":{"type":"integer"},"output_tokens":{"type":"integer"},"cache_read_input_tokens":{"type":"integer"},"cache_creation_input_tokens":{"type":"integer"},"reasoning_tokens":{"type":"integer"},"input_image_tokens":{"type":"integer","description":"Image tokens billed on the input side, 0 when the request carried no image. Priced at its own rate and disjoint from input_tokens, which never includes it."},"output_image_tokens":{"type":"integer","description":"Image tokens the answer was billed for, 0 when the answer held no image. Priced at its own rate and disjoint from output_tokens: an image_generation row reports output_tokens 0 and its render here, so a reconciler reading output_tokens alone sees none of the image traffic."},"image_count":{"type":"integer","description":"Images the request carried, 0 when it carried none. Display only: no rate prices it, so it never belongs in a cost sum."}},"required":["input_tokens","output_tokens","cache_read_input_tokens","cache_creation_input_tokens","reasoning_tokens","input_image_tokens","output_image_tokens","image_count"]},"caps":{"type":"array","items":{"type":"object","properties":{"budget_id":{"type":"string"},"anchor_id":{"type":"string"},"window":{"type":"string"},"on_breach":{"type":"string","enum":["block","warn"]},"limit_usd":{"type":"string","description":"The cap for this end user. Decimal string, up to 9 fractional digits, trailing zeros trimmed, never exponent notation."},"spent_usd":{"type":"string","description":"Spend against that cap. Decimal string, up to 9 fractional digits, trailing zeros trimmed, never exponent notation."},"period_started_at":{"type":"string"}},"required":["budget_id","anchor_id","window","on_breach","limit_usd","spent_usd","period_started_at"]}}},"required":["end_user_id","window","from","to","cost","request_count","usage","caps"]}},"required":["data"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"parameters":[{"in":"query","name":"window","schema":{"type":"string","enum":["day","week","month"],"default":"month"}},{"in":"query","name":"from","schema":{"type":"integer","exclusiveMinimum":0}},{"in":"query","name":"to","schema":{"type":"integer","exclusiveMinimum":0}},{"in":"query","name":"virtual_key_id","schema":{"type":"string","minLength":1,"maxLength":100}},{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"admin_api_key":[]}]}},"/api/gateway/v1/spend-events/replay":{"post":{"operationId":"postApiGatewayV1SpendEventsReplay","tags":["Gateway Spend"],"summary":"Replay spend events to an endpoint","description":"Re-delivers the window's spend envelopes to ONE endpoint through the normal delivery path (per-endpoint stream, retry ladder, delivery log), honoring the endpoint's event subscriptions. Envelope ids are UNCHANGED: your consumer's event-id dedup decides what a redelivery means. Mind your downstream billing system's finite dedup window (Metronome 34 days, Stripe 24h+): replaying older than that window can double-bill on your side, so prefer pull-and-diff for old ranges. The window is capped at 7 days and 10,000 envelopes per call; both caps are checked before any delivery is queued, so a refused replay ships nothing.","responses":{"200":{"description":"Replay accepted","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"endpoint_id":{"type":"string"},"replay_id":{"type":"string"},"replayed":{"type":"integer"},"window":{"type":"object","properties":{"from":{"type":"string"},"to":{"type":"string"}},"required":["from","to"]}},"required":["endpoint_id","replay_id","replayed","window"]}},"required":["data"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"meta":{"type":"object","additionalProperties":{}},"trace_id":{"type":"string"},"span_id":{"type":"string"}},"required":["type","code","message"]}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"from":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"to":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"endpoint_id":{"type":"string","minLength":1,"maxLength":200}},"required":["from","to","endpoint_id"]}}}},"security":[{"admin_api_key":[]}]}},"/api/workflows":{"get":{"operationId":"getApiWorkflows","description":"List all non-archived workflows for the project","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"icon":{"type":["string","null"]},"description":{"type":["string","null"]},"isEvaluator":{"type":"boolean"},"isComponent":{"type":"boolean"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"platformUrl":{"type":"string","format":"uri"}},"required":["id","name","icon","description","isEvaluator","isComponent","createdAt","updatedAt","platformUrl"]}}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"security":[{"project_api_key":[]}]}},"/api/workflows/{id}":{"get":{"operationId":"getApiWorkflowsById","description":"Get a workflow by its ID","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"icon":{"type":["string","null"]},"description":{"type":["string","null"]},"isEvaluator":{"type":"boolean"},"isComponent":{"type":"boolean"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"platformUrl":{"type":"string","format":"uri"}},"required":["id","name","icon","description","isEvaluator","isComponent","createdAt","updatedAt","platformUrl"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Workflow not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]},"patch":{"operationId":"patchApiWorkflowsById","description":"Update a workflow's metadata (name, icon, description)","responses":{"200":{"description":"Workflow updated","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"icon":{"type":["string","null"]},"description":{"type":["string","null"]},"isEvaluator":{"type":"boolean"},"isComponent":{"type":"boolean"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"platformUrl":{"type":"string","format":"uri"}},"required":["id","name","icon","description","isEvaluator","isComponent","createdAt","updatedAt","platformUrl"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Workflow not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1},"icon":{"type":"string"},"description":{"type":"string"}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]},"delete":{"operationId":"deleteApiWorkflowsById","description":"Archive (soft-delete) a workflow","responses":{"200":{"description":"Workflow archived","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"archived":{"type":"boolean"}},"required":["id","archived"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Workflow not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]}},"/api/workflows/{id}/evaluate":{"post":{"operationId":"postApiWorkflowsByIdEvaluate","description":"Trigger an evaluation run of a workflow's committed version through the evaluations pipeline. Evaluate the workflow's attached dataset, inline data, or a platform dataset id; parameters bind as constant entry inputs on every row. Returns a run id and a results URL to poll or open in the browser.","responses":{"200":{"description":"Evaluation started","content":{"application/json":{"schema":{"type":"object","properties":{"run_id":{"type":"string"},"run_url":{"type":"string"},"workflow_version_id":{"type":"string"},"version":{"type":"string"}},"required":["run_id","run_url","workflow_version_id","version"]}}}},"400":{"description":"No committed version to evaluate","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Workflow not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error"]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"version_id":{"type":"string","description":"Committed version to evaluate; defaults to the latest commit"},"data":{"type":"array","items":{"type":"object","additionalProperties":{}},"description":"Inline rows to evaluate instead of the workflow's attached dataset"},"dataset_id":{"type":"string","description":"Platform dataset id to evaluate; mutually exclusive with data"},"parameters":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"}]},"description":"Constant entry inputs applied to every row, e.g. a feature flag or PR number"},"row_indices":{"type":"array","items":{"type":"integer","minimum":0},"description":"Subset of dataset row indices to evaluate"}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"project_api_key":[]}]}}},"components":{"schemas":{"Annotation":{"required":["id","projectId","traceId","createdAt","updatedAt","comment","isThumbsUp","userId","email"],"type":"object","properties":{"id":{"description":"The ID of the annotation","type":"string"},"projectId":{"description":"The ID of the project","type":"string"},"traceId":{"description":"The ID of the trace","type":"string"},"comment":{"description":"The comment of the annotation","type":["string","null"]},"isThumbsUp":{"description":"The thumbs up status of the annotation","type":["boolean","null"]},"userId":{"description":"The ID of the user","type":["string","null"]},"createdAt":{"description":"The created at of the annotation","type":"string"},"updatedAt":{"description":"The updated at of the annotation","type":"string"},"email":{"description":"The email of the user","type":["string","null"]}}},"Error":{"required":["error","message"],"type":"object","properties":{"error":{"type":"integer","format":"int32"},"message":{"type":"string"}}},"SearchRequest":{"type":"object","properties":{"query":{"type":"string"},"startDate":{"type":"string","format":"date-time"},"endDate":{"type":"string","format":"date-time"},"pageSize":{"type":"integer","example":1000},"scrollId":{"type":"string","example":"123"},"filters":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}},"SearchResponse":{"type":"object","properties":{"traces":{"type":"array","items":{"$ref":"#/components/schemas/Trace"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}},"Trace":{"type":"object","properties":{"trace_id":{"type":"string"},"project_id":{"type":"string"},"timestamps":{"$ref":"#/components/schemas/Timestamps"},"input":{"$ref":"#/components/schemas/Input"},"output":{"$ref":"#/components/schemas/Output"},"metadata":{"$ref":"#/components/schemas/Metadata"},"metrics":{"$ref":"#/components/schemas/Metrics"},"indexing_md5s":{"type":"array","items":{"type":"string"}},"error":{"type":"string","nullable":true},"evaluations":{"type":"array","items":{"$ref":"#/components/schemas/Evaluation"}},"contexts":{"type":"array","items":{}}}},"Timestamps":{"type":"object","properties":{"inserted_at":{"type":"integer"},"started_at":{"type":"integer"},"updated_at":{"type":"integer"}}},"Input":{"type":"object","properties":{"value":{"type":"string"}}},"Output":{"type":"object","properties":{"value":{"type":"string"}}},"Metadata":{"type":"object","properties":{"sdk_language":{"type":"string"},"sdk_version":{"type":"string"}}},"Metrics":{"type":"object","properties":{"tokens_estimated":{"type":"boolean"},"completion_tokens":{"type":"integer"},"prompt_tokens":{"type":"integer"},"total_cost":{"type":"number"},"total_time_ms":{"type":"integer"},"first_token_ms":{"type":"integer","nullable":true}}},"Evaluation":{"type":"object","properties":{"evaluation_id":{"type":"string"},"score":{"type":"number"},"timestamps":{"$ref":"#/components/schemas/EvaluationTimestamps"},"evaluator_id":{"type":"string"},"name":{"type":"string"},"details":{"type":"string"},"passed":{"type":"boolean"},"label":{"type":"string","nullable":true},"type":{"type":"string"},"status":{"type":"string"}}},"EvaluationTimestamps":{"type":"object","properties":{"finished_at":{"type":"integer"},"updated_at":{"type":"integer"}}},"Pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"}}},"DatasetPostEntries":{"type":"object","properties":{"entries":{"type":"array","items":{"type":"object","additionalProperties":{}},"example":[{"input":"hi","output":"Hello, how can I help you today?"}]}},"required":["entries"]},"Project":{"type":"object","properties":{"id":{"type":"string","description":"Project ID (project_...)"},"name":{"type":"string"},"slug":{"type":"string"},"language":{"type":"string"},"framework":{"type":"string"},"teamId":{"type":"string"},"piiRedactionLevel":{"type":"string","enum":["STRICT","ESSENTIAL","DISABLED"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"ApiKeyInfo":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"createdAt":{"type":"string","format":"date-time"},"expiresAt":{"type":"string","format":"date-time","nullable":true},"lastUsedAt":{"type":"string","format":"date-time","nullable":true},"revokedAt":{"type":"string","format":"date-time","nullable":true},"roleBindings":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"role":{"type":"string","enum":["ADMIN","MEMBER","VIEWER"]},"scopeType":{"type":"string","enum":["ORGANIZATION","TEAM","PROJECT"]},"scopeId":{"type":"string"}}}}}},"JsonValue":{"description":"Any JSON value: a string, number, boolean, null, array, or object.","anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"null"},{"type":"array","items":{"$ref":"#/components/schemas/JsonValue"}},{"type":"object","additionalProperties":{"$ref":"#/components/schemas/JsonValue"}}]}},"securitySchemes":{"project_api_key":{"type":"apiKey","in":"header","name":"X-Auth-Token","description":"Project API key for sending traces and accessing project-scoped resources. Format: sk-lw-... (no underscore). Obtain one by creating a project via the Admin API or the LangWatch UI."},"admin_api_key":{"type":"http","scheme":"bearer","description":"Admin API key for organization-level operations (managing projects, API keys). Create one in Settings > API Keys or via POST /api/api-keys. Format: sk-lw-{id}_{secret}."},"instance_admin_key":{"type":"http","scheme":"bearer","description":"Instance administrator key, set as LANGWATCH_INSTANCE_ADMIN_API_KEY on a self-hosted deployment. It exists to create the first organization, before any organization key does; every other management API takes an organization key instead."},"scim_bearer":{"type":"http","scheme":"bearer","description":"SCIM token for one organization's directory connection, created with POST /api/scim-tokens or in Settings > SCIM. It authenticates provisioning calls only, and stops working if the organization's Enterprise plan lapses."}}}}