openapi: 3.1.0 info: title: Laminar API version: 1.0.0 description: Public HTTP API for ingesting and managing data in a Laminar project. license: name: Apache 2.0 identifier: Apache-2.0 servers: - url: https://api.lmnr.ai description: Laminar Cloud security: - projectApiKey: [] tags: - name: Ingestion description: Send telemetry data to Laminar. - name: Traces description: Update trace data after ingestion. - name: SQL description: Query project data with read-only SQL. - name: Projects description: Resolve project information. - name: Datasets description: Create, read, update, and delete datasets and add datapoints. - name: Evaluations description: Create evaluation runs and record their results. - name: Labeling queues description: Add items to labeling queues. - name: Signals description: Manage automated evaluations of project traces. - name: LLM profiles description: Configure the workspace LLM credentials and models the playground and self-hosted Signals run on. paths: /v1/traces: post: tags: [Ingestion] summary: Ingest OpenTelemetry traces description: Accepts an OTLP ExportTraceServiceRequest encoded as protobuf or OTLP JSON. operationId: ingestTraces security: [{ projectApiKey: [] }, { ingestApiKey: [] }] requestBody: required: true content: application/x-protobuf: schema: { type: string, contentMediaType: application/x-protobuf } application/json: schema: { type: object, additionalProperties: true } responses: "200": { description: Trace batch accepted. } "400": { $ref: "#/components/responses/BadRequest" } "401": { $ref: "#/components/responses/Unauthorized" } "413": { $ref: "#/components/responses/PayloadTooLarge" } "429": { description: Ingestion rate limit exceeded. } /v1/spans: post: tags: [Ingestion] summary: Create spans description: Ingests a batch of spans using Laminar's JSON span format. operationId: createSpans security: [{ projectApiKey: [] }, { ingestApiKey: [] }] requestBody: required: true content: application/json: schema: type: array items: { $ref: "#/components/schemas/CreateSpanRequest" } responses: "200": description: Spans accepted. content: application/json: schema: type: array items: { $ref: "#/components/schemas/CreateSpanResponse" } "400": { $ref: "#/components/responses/BadRequest" } "401": { $ref: "#/components/responses/Unauthorized" } "413": { $ref: "#/components/responses/PayloadTooLarge" } /v1/logs: post: tags: [Ingestion] summary: Ingest OpenTelemetry logs description: >- Accepts an OTLP ExportLogsServiceRequest encoded as protobuf. JSON-encoded OTLP is not accepted. This endpoint is in beta: ingested logs are stored in the `logs` table and can only be queried with SQL. They are not shown anywhere in the Laminar UI, and Signals do not read them when analyzing traces. operationId: ingestLogs security: [{ projectApiKey: [] }, { ingestApiKey: [] }] requestBody: required: true content: application/x-protobuf: schema: { type: string, contentMediaType: application/x-protobuf } responses: "200": { description: Log batch accepted. } "400": { $ref: "#/components/responses/BadRequest" } "401": { $ref: "#/components/responses/Unauthorized" } "413": { $ref: "#/components/responses/PayloadTooLarge" } /v1/labeling_queues/{queue_id}/items: post: tags: [Labeling queues] summary: Add labeling queue items description: Adds items to a labeling queue, optionally deduplicating them with idempotency keys. operationId: createLabelingQueueItems security: [{ projectApiKey: [] }, { ingestApiKey: [] }] parameters: - { $ref: "#/components/parameters/QueueId" } requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/CreateLabelingQueueItemsRequest" } responses: "201": description: Items created. content: application/json: schema: { type: array, items: { $ref: "#/components/schemas/LabelingQueueItemResponse" } } "400": { $ref: "#/components/responses/BadRequest" } "401": { $ref: "#/components/responses/Unauthorized" } "404": { $ref: "#/components/responses/NotFound" } /v1/sql/query: post: tags: [SQL] summary: Query project data description: Executes a validated, read-only SQL query scoped to the authenticated project. operationId: executeSqlQuery requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/SqlQueryRequest" } responses: "200": description: Query results. content: application/json: schema: { $ref: "#/components/schemas/SqlQueryResponse" } "400": { $ref: "#/components/responses/BadRequest" } "401": { $ref: "#/components/responses/Unauthorized" } "429": { description: SQL query rate limit exceeded. } /v1/project: get: tags: [Projects] summary: Get the current project description: Returns the project ID associated with the supplied API key. operationId: getCurrentProject responses: "200": description: Current project. content: application/json: schema: type: object required: [projectId] properties: projectId: { $ref: "#/components/schemas/Uuid" } "401": { $ref: "#/components/responses/Unauthorized" } /v1/datasets: get: tags: [Datasets] summary: List datasets description: Lists project datasets, optionally filtered by dataset ID or name. operationId: listDatasets parameters: - { name: id, in: query, schema: { $ref: "#/components/schemas/Uuid" } } - { name: name, in: query, schema: { type: string } } responses: "200": description: Matching datasets. content: application/json: schema: { type: array, items: { $ref: "#/components/schemas/Dataset" } } "401": { $ref: "#/components/responses/Unauthorized" } post: tags: [Datasets] summary: Create a dataset description: Creates an empty dataset. Dataset names do not need to be unique. operationId: createDataset requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/DatasetNameRequest" } responses: "201": description: Dataset created. content: application/json: schema: { $ref: "#/components/schemas/Dataset" } "400": { $ref: "#/components/responses/BadRequest" } "401": { $ref: "#/components/responses/Unauthorized" } /v1/datasets/{dataset_id}: parameters: - { $ref: "#/components/parameters/DatasetId" } get: tags: [Datasets] summary: Get a dataset description: Returns a dataset by its canonical ID. operationId: getDataset responses: "200": description: Dataset found. content: application/json: schema: { $ref: "#/components/schemas/Dataset" } "401": { $ref: "#/components/responses/Unauthorized" } "404": { $ref: "#/components/responses/NotFound" } patch: tags: [Datasets] summary: Update a dataset description: Renames a dataset. Dataset names do not need to be unique. operationId: updateDataset requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/DatasetNameRequest" } responses: "200": description: Dataset updated. content: application/json: schema: { $ref: "#/components/schemas/Dataset" } "400": { $ref: "#/components/responses/BadRequest" } "401": { $ref: "#/components/responses/Unauthorized" } "404": { $ref: "#/components/responses/NotFound" } delete: tags: [Datasets] summary: Delete a dataset description: Deletes a dataset and its datapoints. operationId: deleteDataset responses: "200": description: Dataset deleted. Returns the deleted dataset. content: application/json: schema: { $ref: "#/components/schemas/Dataset" } "401": { $ref: "#/components/responses/Unauthorized" } "404": { $ref: "#/components/responses/NotFound" } /v1/datasets/datapoints: get: tags: [Datasets] summary: List dataset datapoints description: Returns a paginated page of datapoints from a dataset identified by ID or name. operationId: listDatasetDatapoints parameters: - { name: datasetId, in: query, schema: { $ref: "#/components/schemas/Uuid" } } - { name: datasetName, in: query, schema: { type: string } } - { name: limit, in: query, required: true, schema: { type: integer, format: int64, minimum: 1, maximum: 1000 } } - { name: offset, in: query, required: true, schema: { type: integer, format: int64, minimum: 0 } } responses: "200": description: A page of datapoints. content: application/json: schema: { $ref: "#/components/schemas/DatapointPage" } "400": { $ref: "#/components/responses/BadRequest" } "401": { $ref: "#/components/responses/Unauthorized" } "404": { $ref: "#/components/responses/NotFound" } post: tags: [Datasets] summary: Create dataset datapoints description: Adds datapoints to a dataset and can optionally create the dataset when identified by name. operationId: createDatasetDatapoints requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/CreateDatapointsRequest" } responses: "200": { $ref: "#/components/responses/DatapointsCreated" } "201": { $ref: "#/components/responses/DatapointsCreated" } "400": { $ref: "#/components/responses/BadRequest" } "401": { $ref: "#/components/responses/Unauthorized" } "404": { $ref: "#/components/responses/NotFound" } "409": { description: A dataset with the requested name already exists. } /v1/signals: post: tags: [Signals] summary: Create a Signal description: | Creates a Signal with the first server-managed configuration version. `llmProfileId` and `model` are available only on self-hosted deployments. Provide both fields together. Laminar Cloud rejects them. operationId: createSignal requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/CreateSignalRequest" } responses: "201": description: Signal created. content: application/json: schema: { $ref: "#/components/schemas/Signal" } "400": { $ref: "#/components/responses/BadRequest" } "401": { $ref: "#/components/responses/Unauthorized" } "409": { $ref: "#/components/responses/Conflict" } get: tags: [Signals] summary: List Signals description: Lists Signals in the project, optionally filtering by a name substring. operationId: listSignals parameters: - name: name in: query schema: { type: string } responses: "200": description: Project Signals. content: application/json: schema: { $ref: "#/components/schemas/SignalList" } "401": { $ref: "#/components/responses/Unauthorized" } /v1/signals/{signal_id}: parameters: - { $ref: "#/components/parameters/SignalId" } get: tags: [Signals] summary: Get a Signal description: Returns a Signal in the authenticated project. operationId: getSignal responses: "200": description: Signal details. content: application/json: schema: { $ref: "#/components/schemas/Signal" } "401": { $ref: "#/components/responses/Unauthorized" } "404": { $ref: "#/components/responses/NotFound" } patch: tags: [Signals] summary: Update a Signal description: | Updates a Signal. An update that changes the effective Signal configuration increments its server-managed version. `llmProfileId` and `model` are available only on self-hosted deployments. Provide both fields together to change the Signal's LLM route. Laminar Cloud rejects them. operationId: updateSignal requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/UpdateSignalRequest" } responses: "200": description: Signal updated. content: application/json: schema: { $ref: "#/components/schemas/Signal" } "400": { $ref: "#/components/responses/BadRequest" } "401": { $ref: "#/components/responses/Unauthorized" } "404": { $ref: "#/components/responses/NotFound" } "409": { $ref: "#/components/responses/Conflict" } delete: tags: [Signals] summary: Delete a Signal description: | Deletes a Signal and returns its final state. Deleting a Signal also deletes all of its alerts and events and is irreversible. We recommend disabling the Signal instead. You can disable it from the UI or through the [Update a Signal](/api-reference/signals/update-a-signal) endpoint by setting `disabled` to `true`. operationId: deleteSignal responses: "200": description: Signal deleted. content: application/json: schema: { $ref: "#/components/schemas/Signal" } "401": { $ref: "#/components/responses/Unauthorized" } "404": { $ref: "#/components/responses/NotFound" } /v1/llm-profiles: get: tags: [LLM profiles] summary: List LLM profiles description: | Lists every LLM profile in the authenticated project's workspace. operationId: listLlmProfiles responses: "200": description: Workspace LLM profiles. Secret values are masked. content: application/json: schema: { $ref: "#/components/schemas/LlmProfileList" } "401": { $ref: "#/components/responses/Unauthorized" } "404": { $ref: "#/components/responses/NotFound" } post: tags: [LLM profiles] summary: Create an LLM profile description: | Creates an LLM profile in the authenticated project's workspace. Secrets are accepted as plaintext over TLS, stored encrypted, and never returned unmasked. operationId: createLlmProfile requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/CreateLlmProfileRequest" } responses: "200": description: LLM profile created. Secret values are masked. content: application/json: schema: { $ref: "#/components/schemas/LlmProfile" } "400": { $ref: "#/components/responses/BadRequest" } "401": { $ref: "#/components/responses/Unauthorized" } "404": { $ref: "#/components/responses/NotFound" } "409": { $ref: "#/components/responses/Conflict" } /v1/llm-profiles/{profile_id}: parameters: - { $ref: "#/components/parameters/LlmProfileId" } get: tags: [LLM profiles] summary: Get an LLM profile description: | Returns an LLM profile from the authenticated project's workspace. Secret values are masked. operationId: getLlmProfile responses: "200": description: LLM profile details. content: application/json: schema: { $ref: "#/components/schemas/LlmProfile" } "401": { $ref: "#/components/responses/Unauthorized" } "404": { $ref: "#/components/responses/NotFound" } patch: tags: [LLM profiles] summary: Update an LLM profile description: | Updates an LLM profile. Omitted fields retain their stored values, `models` replaces the complete model list, a supplied `config` replaces the whole stored config object, and supplied secrets are merged with stored secrets. Removing a model used by a Signal returns `409 Conflict`. operationId: updateLlmProfile requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/UpdateLlmProfileRequest" } responses: "200": description: LLM profile updated. Secret values are masked. content: application/json: schema: { $ref: "#/components/schemas/LlmProfile" } "400": { $ref: "#/components/responses/BadRequest" } "401": { $ref: "#/components/responses/Unauthorized" } "404": { $ref: "#/components/responses/NotFound" } "409": { $ref: "#/components/responses/Conflict" } delete: tags: [LLM profiles] summary: Delete an LLM profile description: | Deletes an LLM profile and returns its final state. A profile used by a Signal cannot be deleted. The API returns `409 Conflict` until every Signal stops using it. operationId: deleteLlmProfile responses: "200": description: LLM profile deleted. Secret values are masked. content: application/json: schema: { $ref: "#/components/schemas/LlmProfile" } "401": { $ref: "#/components/responses/Unauthorized" } "404": { $ref: "#/components/responses/NotFound" } "409": { $ref: "#/components/responses/Conflict" } /v1/evals: post: tags: [Evaluations] summary: Create an evaluation description: Creates an evaluation run, generating a name when none is supplied. operationId: createEvaluation requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/CreateEvaluationRequest" } responses: "200": description: Evaluation created. content: application/json: schema: { $ref: "#/components/schemas/Evaluation" } "400": { $ref: "#/components/responses/BadRequest" } "401": { $ref: "#/components/responses/Unauthorized" } /v1/evals/{eval_id}: post: tags: [Evaluations] summary: Update an evaluation description: Updates an evaluation's name and/or metadata; omitted fields remain unchanged. operationId: updateEvaluation parameters: - { $ref: "#/components/parameters/EvaluationId" } requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/UpdateEvaluationRequest" } responses: "200": description: Evaluation updated. content: application/json: schema: { $ref: "#/components/schemas/Evaluation" } "400": { $ref: "#/components/responses/BadRequest" } "401": { $ref: "#/components/responses/Unauthorized" } "404": { $ref: "#/components/responses/NotFound" } /v1/evals/{eval_id}/datapoints: post: tags: [Evaluations] summary: Add evaluation datapoints description: Adds result datapoints to an evaluation run. operationId: createEvaluationDatapoints parameters: - { $ref: "#/components/parameters/EvaluationId" } requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/CreateEvaluationDatapointsRequest" } responses: "200": description: Datapoints added; returns the evaluation ID. content: application/json: schema: { $ref: "#/components/schemas/Uuid" } "400": { $ref: "#/components/responses/BadRequest" } "401": { $ref: "#/components/responses/Unauthorized" } /v1/evals/{eval_id}/datapoints/{datapoint_id}: post: tags: [Evaluations] summary: Update an evaluation datapoint description: Updates a datapoint's executor output, scores, and optional trace association. operationId: updateEvaluationDatapoint parameters: - { $ref: "#/components/parameters/EvaluationId" } - { $ref: "#/components/parameters/DatapointId" } requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/UpdateEvaluationDatapointRequest" } responses: "200": description: Datapoint updated; returns the datapoint ID. content: application/json: schema: { $ref: "#/components/schemas/Uuid" } "400": { $ref: "#/components/responses/BadRequest" } "401": { $ref: "#/components/responses/Unauthorized" } components: securitySchemes: projectApiKey: type: http scheme: bearer bearerFormat: Project API key description: A Laminar project API key. ingestApiKey: type: http scheme: bearer bearerFormat: Ingest-only API key description: A project API key restricted to ingestion operations. parameters: DatasetId: name: dataset_id in: path required: true schema: { $ref: "#/components/schemas/Uuid" } QueueId: name: queue_id in: path required: true schema: { $ref: "#/components/schemas/Uuid" } EvaluationId: name: eval_id in: path required: true schema: { $ref: "#/components/schemas/Uuid" } DatapointId: name: datapoint_id in: path required: true schema: { $ref: "#/components/schemas/Uuid" } SignalId: name: signal_id in: path required: true schema: { $ref: "#/components/schemas/Uuid" } LlmProfileId: name: profile_id in: path required: true schema: { $ref: "#/components/schemas/Uuid" } responses: Success: { description: Request completed successfully. } BadRequest: description: Invalid request. content: application/json: schema: { $ref: "#/components/schemas/Error" } Unauthorized: description: Missing or invalid API key. NotFound: description: The requested resource was not found in this project. content: application/json: schema: { $ref: "#/components/schemas/Error" } PayloadTooLarge: { description: The request exceeds the configured HTTP payload limit. } Conflict: description: A resource with the requested name already exists. content: application/json: schema: { $ref: "#/components/schemas/Error" } DatapointsCreated: description: Datapoints created; status 201 means the dataset was also created. content: application/json: schema: { $ref: "#/components/schemas/CreateDatapointsResponse" } schemas: Uuid: { type: string, format: uuid } JsonValue: {} Error: oneOf: - { type: object, properties: { error: { type: string } }, required: [error] } - { type: string } CreateSpanRequest: type: object required: [name, startTime, endTime, traceId, spanId] properties: name: { type: string } spanType: type: [string, "null"] description: "Note: The backend may still accept `PIPELINE` and `HUMAN_EVALUATOR`, but they are undocumented, and should not be used." enum: [DEFAULT, LLM, EXECUTOR, EVALUATOR, EVALUATION, TOOL, CACHED, null] startTime: { type: string, format: date-time } endTime: { type: string, format: date-time } input: { $ref: "#/components/schemas/JsonValue" } output: { $ref: "#/components/schemas/JsonValue" } attributes: { type: [object, "null"], additionalProperties: true } traceId: { $ref: "#/components/schemas/Uuid" } spanId: { $ref: "#/components/schemas/Uuid" } parentSpanId: { oneOf: [{ $ref: "#/components/schemas/Uuid" }, { type: "null" }] } CreateSpanResponse: type: object required: [spanId, traceId] properties: spanId: { $ref: "#/components/schemas/Uuid" } traceId: { $ref: "#/components/schemas/Uuid" } CreateLabelingQueueItemsRequest: type: object required: [items] properties: items: type: array minItems: 1 items: { $ref: "#/components/schemas/LabelingQueueItemRequest" } LabelingQueueItemRequest: type: object required: [data, target] properties: data: { $ref: "#/components/schemas/JsonValue" } target: { $ref: "#/components/schemas/JsonValue" } metadata: { type: object, additionalProperties: true, default: {} } idempotencyKey: { type: [string, "null"] } LabelingQueueItemResponse: type: object required: [id, createdAt] properties: id: { $ref: "#/components/schemas/Uuid" } createdAt: { type: string, format: date-time } SqlQueryRequest: type: object required: [query] properties: query: { type: string } parameters: { type: object, additionalProperties: true, default: {} } SqlQueryResponse: type: object required: [data] properties: data: { type: array, items: { $ref: "#/components/schemas/JsonValue" } } DatasetNameRequest: type: object required: [name] properties: name: type: string minLength: 1 description: Dataset name. Names are stored as supplied and do not need to be unique. Dataset: type: object required: [id, name, projectId, createdAt] properties: id: { $ref: "#/components/schemas/Uuid" } name: { type: string } projectId: { $ref: "#/components/schemas/Uuid" } createdAt: { type: string, format: date-time } Datapoint: type: object required: [id, datasetId, data, metadata, createdAt] properties: id: { $ref: "#/components/schemas/Uuid" } datasetId: { $ref: "#/components/schemas/Uuid" } data: { $ref: "#/components/schemas/JsonValue" } target: { $ref: "#/components/schemas/JsonValue" } metadata: { type: object, additionalProperties: true } createdAt: { type: string, format: date-time } DatapointPage: type: object required: [totalCount, items, anyInProject] properties: totalCount: { type: integer, format: int64 } items: { type: array, items: { $ref: "#/components/schemas/Datapoint" } } anyInProject: { type: boolean } NewDatapoint: type: object required: [data] properties: id: { oneOf: [{ $ref: "#/components/schemas/Uuid" }, { type: "null" }] } data: { $ref: "#/components/schemas/JsonValue" } target: { $ref: "#/components/schemas/JsonValue" } metadata: { type: object, additionalProperties: true, default: {} } CreateDatapointsRequest: type: object required: [datapoints] description: Supply exactly one of datasetId or datasetName. properties: datasetId: { $ref: "#/components/schemas/Uuid" } datasetName: { type: string } datapoints: { type: array, items: { $ref: "#/components/schemas/NewDatapoint" } } createDataset: { type: boolean, default: false } oneOf: - { required: [datasetId] } - { required: [datasetName] } CreateDatapointsResponse: type: object required: [message, datasetId, count, datapointInfo] properties: message: { type: string } datasetId: { $ref: "#/components/schemas/Uuid" } count: { type: integer } datapointInfo: type: array items: type: object required: [id, createdAt] properties: id: { $ref: "#/components/schemas/Uuid" } createdAt: { type: string, format: date-time } SignalTrigger: oneOf: - type: object required: [type] properties: type: { type: string, const: rootSpanFinished } - type: object required: [type, spanNames] properties: type: { type: string, const: spanName } spanNames: type: array minItems: 1 items: { type: string } SignalFilter: type: object required: [column, operator, value] properties: column: type: string enum: [total_token_count, status, span_names, tags] operator: type: string enum: [eq, ne, gt, gte, lt, lte, includes, not_includes] value: { $ref: "#/components/schemas/JsonValue" } description: Operators and value shapes are validated for the selected column. SignalDefinitionFields: type: object properties: name: { type: string, maxLength: 255 } prompt: { type: string } structuredOutput: type: object additionalProperties: true description: JSON Schema for the Signal's structured result. sampleRate: type: [integer, "null"] minimum: 1 maximum: 95 description: Percentage of matching traces to sample; null clears sampling on update. disabled: { type: boolean } trigger: { $ref: "#/components/schemas/SignalTrigger" } filters: type: array items: { $ref: "#/components/schemas/SignalFilter" } mode: { type: string, enum: [batch, realtime] } llmProfileId: oneOf: - { $ref: "#/components/schemas/Uuid" } - { type: "null" } description: Self-hosted only. Workspace LLM profile used to evaluate the Signal. Provide with `model`; omit both fields on update to keep the existing route. model: type: [string, "null"] description: Self-hosted only. Model selected from `llmProfileId`. Provide both fields together. CreateSignalRequest: allOf: - { $ref: "#/components/schemas/SignalDefinitionFields" } - type: object required: [name, prompt, structuredOutput] UpdateSignalRequest: $ref: "#/components/schemas/SignalDefinitionFields" Signal: allOf: - { $ref: "#/components/schemas/SignalDefinitionFields" } - type: object required: [ id, projectId, name, prompt, structuredOutput, sampleRate, disabled, createdAt, trigger, filters, mode, version, llmProfileId, llmProfileName, model, ] properties: id: { $ref: "#/components/schemas/Uuid" } projectId: { $ref: "#/components/schemas/Uuid" } createdAt: { type: string, format: date-time } version: type: integer format: int32 minimum: 1 readOnly: true description: Server-managed version of the Signal configuration. llmProfileName: type: [string, "null"] readOnly: true description: Display name of the selected workspace LLM profile. SignalList: type: object required: [signals] properties: signals: type: array items: { $ref: "#/components/schemas/Signal" } LlmProfileProvider: type: string enum: [ openai_completions, openai_responses, anthropic, gemini, groq, mistral, bedrock, azure_chat_completions, azure_responses, azure_anthropic, custom, custom_responses, ] LlmProfileAuth: oneOf: - type: object required: [type] properties: type: { type: string, const: api_key } - type: object required: [type, accessKeyId] properties: type: { type: string, const: aws_keys } accessKeyId: { type: string, maxLength: 256 } - type: object required: [type] properties: type: { type: string, const: bearer_token } LlmProfileConfig: type: object properties: auth: { $ref: "#/components/schemas/LlmProfileAuth" } region: { type: string, maxLength: 64 } resourceId: { type: string, maxLength: 256 } baseUrl: { type: string, format: uri } apiVersion: { type: string, maxLength: 64 } headerNames: type: array maxItems: 32 uniqueItems: true items: { type: string, maxLength: 256 } description: Provider-specific non-secret configuration. Azure requires exactly one of `resourceId` or `baseUrl`; Bedrock requires `region`; custom providers require `baseUrl`. LlmProfileSecretsInput: type: object writeOnly: true properties: apiKey: { type: string, format: password, maxLength: 8192 } secretAccessKey: { type: string, format: password, maxLength: 8192 } token: { type: string, format: password, maxLength: 8192 } headers: type: object additionalProperties: { type: string, format: password, maxLength: 8192 } description: Plaintext credentials. Required fields depend on the provider and authentication type. LlmProfileSecrets: type: object readOnly: true required: [apiKey, secretAccessKey, token, headers] properties: apiKey: { type: [string, "null"], description: Masked API key. } secretAccessKey: { type: [string, "null"], description: Masked AWS secret access key. } token: { type: [string, "null"], description: Masked bearer token. } headers: type: array items: { type: string } description: Names of stored custom headers; values are never returned. CreateLlmProfileRequest: type: object required: [name, provider, models] properties: name: { type: string, maxLength: 255 } provider: { $ref: "#/components/schemas/LlmProfileProvider" } config: { $ref: "#/components/schemas/LlmProfileConfig" } secrets: { $ref: "#/components/schemas/LlmProfileSecretsInput" } models: type: array minItems: 1 maxItems: 64 uniqueItems: true items: { type: string, maxLength: 256 } UpdateLlmProfileRequest: type: object properties: name: { type: string, maxLength: 255 } provider: allOf: - { $ref: "#/components/schemas/LlmProfileProvider" } description: When changing the provider, `config` is required. config: { $ref: "#/components/schemas/LlmProfileConfig" } secrets: allOf: - { $ref: "#/components/schemas/LlmProfileSecretsInput" } description: Supplied values replace matching secrets; omitted values remain unchanged. models: type: array minItems: 1 maxItems: 64 uniqueItems: true items: { type: string, maxLength: 256 } description: Replaces the complete model list when supplied. LlmProfile: type: object required: [id, workspaceId, name, provider, config, models, secrets, createdAt, updatedAt] properties: id: { $ref: "#/components/schemas/Uuid" } workspaceId: { $ref: "#/components/schemas/Uuid" } name: { type: string } provider: { $ref: "#/components/schemas/LlmProfileProvider" } config: { $ref: "#/components/schemas/LlmProfileConfig" } models: type: array items: { type: string } secrets: { $ref: "#/components/schemas/LlmProfileSecrets" } createdAt: { type: string, format: date-time } updatedAt: { type: string, format: date-time } LlmProfileList: type: object required: [llmProfiles] properties: llmProfiles: type: array items: { $ref: "#/components/schemas/LlmProfile" } CreateEvaluationRequest: type: object properties: name: { type: [string, "null"] } groupName: { type: [string, "null"], default: default } metadata: { $ref: "#/components/schemas/JsonValue" } UpdateEvaluationRequest: type: object properties: name: { type: [string, "null"] } metadata: description: Replaces the complete evaluation metadata object when supplied. $ref: "#/components/schemas/JsonValue" Evaluation: type: object required: [id, createdAt, name, projectId, groupId] properties: id: { $ref: "#/components/schemas/Uuid" } createdAt: { type: string, format: date-time } name: { type: string } projectId: { $ref: "#/components/schemas/Uuid" } groupId: { type: string } metadata: { $ref: "#/components/schemas/JsonValue" } CreateEvaluationDatapointsRequest: type: object required: [points] properties: groupName: { type: [string, "null"], default: default } points: type: array items: { $ref: "#/components/schemas/EvaluationDatapoint" } EvaluationDatapoint: type: object required: [data] properties: data: { $ref: "#/components/schemas/JsonValue" } index: { type: integer, format: int32, default: 0 } id: { $ref: "#/components/schemas/Uuid" } target: { $ref: "#/components/schemas/JsonValue" } metadata: { type: [object, "null"], additionalProperties: true } executorOutput: { $ref: "#/components/schemas/JsonValue" } traceId: { $ref: "#/components/schemas/Uuid" } scores: type: object additionalProperties: { type: [number, "null"], format: double } datasetLink: oneOf: - { $ref: "#/components/schemas/EvaluationDatasetLink" } - { type: "null" } EvaluationDatasetLink: type: object required: [datasetId, datapointId, createdAt] properties: datasetId: { $ref: "#/components/schemas/Uuid" } datapointId: { $ref: "#/components/schemas/Uuid" } createdAt: { type: string, format: date-time } UpdateEvaluationDatapointRequest: type: object required: [scores] properties: executorOutput: { $ref: "#/components/schemas/JsonValue" } scores: type: object additionalProperties: { type: [number, "null"], format: double } traceId: { oneOf: [{ $ref: "#/components/schemas/Uuid" }, { type: "null" }] }