# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json
imports:
  pagination: ./utils/pagination.yml
  commons: ./commons.yml
service:
  auth: true
  base-path: /api/public
  endpoints:
    batch:
      docs: |
        **Legacy endpoint for batch ingestion for Langfuse Observability.**

        -> Please use the OpenTelemetry endpoint (`/api/public/otel`). Learn more: https://langfuse.com/integrations/native/opentelemetry

        Within each batch, there can be multiple events.
        Each event has a type, an id, a timestamp, metadata and a body.
        Internally, we refer to this as the "event envelope" as it tells us something about the event but not the trace.
        We use the event id within this envelope to deduplicate messages to avoid processing the same event twice, i.e. the event id should be unique per request.
        The event.body.id is the ID of the actual trace and will be used for updates and will be visible within the Langfuse App.
        I.e. if you want to update a trace, you'd use the same body id, but separate event IDs.

        Notes:
        - Introduction to data model: https://langfuse.com/docs/observability/data-model
        - Batch sizes are limited to 3.5 MB in total. You need to adjust the number of events per batch accordingly.
        - The API does not return a 4xx status code for input errors. Instead, it responds with a 207 status code, which includes a list of the encountered errors.
      method: POST
      path: /ingestion
      request:
        name: IngestionRequest
        body:
          properties:
            batch:
              type: list<IngestionEvent>
              docs: "Batch of tracing events to be ingested. Discriminated by attribute `type`."
            metadata:
              type: optional<unknown>
              docs: Optional. Metadata field used by the Langfuse SDKs for debugging.
      response:
        type: IngestionResponse
        status-code: 207
      examples:
        # Trace Create Request
        - request:
            batch:
              - id: abcdef-1234-5678-90ab
                timestamp: "2022-01-01T00:00:00.000Z"
                type: "trace-create"
                body:
                  id: abcdef-1234-5678-90ab
                  timestamp: "2022-01-01T00:00:00.000Z"
                  environment: "production"
                  name: "My Trace"
                  userId: "1234-5678-90ab-cdef"
                  input: "My input"
                  output: "My output"
                  sessionId: "1234-5678-90ab-cdef"
                  release: "1.0.0"
                  version: "1.0.0"
                  metadata: "My metadata"
                  tags: ["tag1", "tag2"]
                  public: true
          response:
            body:
              successes:
                - id: abcdef-1234-5678-90ab
                  status: 201
              errors: []

        # Observation Create Request
        - request:
            batch:
              - id: abcdef-1234-5678-90ab
                timestamp: "2022-01-01T00:00:00.000Z"
                type: "span-create"
                body:
                  id: abcdef-1234-5678-90ab
                  traceId: "1234-5678-90ab-cdef"
                  startTime: "2022-01-01T00:00:00.000Z"
                  environment: "test"
          response:
            body:
              successes:
                - id: abcdef-1234-5678-90ab
                  status: 201
              errors: []

        # Score Create Request
        - request:
            batch:
              - id: abcdef-1234-5678-90ab
                timestamp: "2022-01-01T00:00:00.000Z"
                type: "score-create"
                body:
                  id: abcdef-1234-5678-90ab
                  traceId: "1234-5678-90ab-cdef"
                  name: "My Score"
                  value: 0.9
                  environment: "default"
          response:
            body:
              successes:
                - id: abcdef-1234-5678-90ab
                  status: 201
              errors: []

types:
  IngestionEvent:
    discriminant: "type"
    union:
      trace-create:
        type: TraceEvent
        docs: Creates a new trace. Upserts on id for updates if trace with id exists.
      score-create:
        type: ScoreEvent
        docs: Creates a new score. Upserts on id for updates if score with id exists.
      span-create:
        type: CreateSpanEvent
        docs: Creates a new span.
      span-update:
        type: UpdateSpanEvent
        docs: Updates span based on id.
      generation-create:
        type: CreateGenerationEvent
        docs: Creates a new generation.
      generation-update:
        type: UpdateGenerationEvent
        docs: Updates a generation based on id.
      event-create:
        type: CreateEventEvent
        docs: Creates an event.

      sdk-log:
        type: SDKLogEvent
        docs: Langfuse SDKs only, used for debugging purposes.

      # both are legacy
      observation-create:
        type: CreateObservationEvent
        docs: Deprecated event type
      observation-update:
        type: UpdateObservationEvent
        docs: Deprecated event type

  ObservationType:
    enum:
      - SPAN
      - GENERATION
      - EVENT
      - AGENT
      - TOOL
      - CHAIN
      - RETRIEVER
      - EVALUATOR
      - EMBEDDING
      - GUARDRAIL

  IngestionUsage:
    discriminated: false
    union:
      - commons.Usage
      - OpenAIUsage

  OpenAIUsage:
    docs: Usage interface of OpenAI for improved compatibility.
    properties:
      promptTokens: optional<integer>
      completionTokens: optional<integer>
      totalTokens: optional<integer>

  OptionalObservationBody:
    properties:
      traceId: optional<string>
      name: optional<string>
      startTime: optional<datetime>
      metadata: optional<unknown>
      input: optional<unknown>
      output: optional<unknown>
      level: optional<commons.ObservationLevel>
      statusMessage: optional<string>
      parentObservationId: optional<string>
      version: optional<string>
      environment: optional<string>

  CreateEventBody:
    extends: OptionalObservationBody
    properties:
      id: optional<string>

  UpdateEventBody:
    extends: OptionalObservationBody
    properties:
      id: string

  CreateSpanBody:
    extends: CreateEventBody
    properties:
      endTime: optional<datetime>

  UpdateSpanBody:
    extends: UpdateEventBody
    properties:
      endTime: optional<datetime>

  CreateGenerationBody:
    extends: CreateSpanBody
    properties:
      completionStartTime: optional<datetime>
      model: optional<string>
      modelParameters: optional<map<string, commons.MapValue>>
      usage: optional<IngestionUsage>
      usageDetails: optional<UsageDetails>
      costDetails: optional<map<string, double>>
      promptName: optional<string>
      promptVersion: optional<integer>

  UpdateGenerationBody:
    extends: UpdateSpanBody
    properties:
      completionStartTime: optional<datetime>
      model: optional<string>
      modelParameters: optional<map<string, commons.MapValue>>
      usage: optional<IngestionUsage>
      promptName: optional<string>
      usageDetails: optional<UsageDetails>
      costDetails: optional<map<string, double>>
      promptVersion: optional<integer>

  ObservationBody:
    properties:
      id: optional<string>
      traceId: optional<string>
      type: ObservationType
      name: optional<string>
      startTime: optional<datetime>
      endTime: optional<datetime>
      completionStartTime: optional<datetime>
      model: optional<string>
      modelParameters: optional<map<string, commons.MapValue>>
      input: optional<unknown>
      version: optional<string>
      metadata: optional<unknown>
      output: optional<unknown>
      usage: optional<commons.Usage>
      level: optional<commons.ObservationLevel>
      statusMessage: optional<string>
      parentObservationId: optional<string>
      environment: optional<string>

  TraceBody:
    properties:
      id: optional<string>
      timestamp: optional<datetime>
      name: optional<string>
      userId: optional<string>
      input: optional<unknown>
      output: optional<unknown>
      sessionId: optional<string>
      release: optional<string>
      version: optional<string>
      metadata: optional<unknown>
      tags: optional<list<string>>
      environment: optional<string>
      public:
        type: optional<boolean>
        docs: Make trace publicly accessible via url

  SDKLogBody:
    properties:
      log: unknown

  ScoreBody:
    properties:
      id: optional<string>
      traceId: optional<string>
      sessionId: optional<string>
      observationId: optional<string>
      datasetRunId: optional<string>
      name: string
      environment: optional<string>
      value:
        type: commons.CreateScoreValue
        docs: The value of the score. Must be passed as string for categorical scores, and numeric for boolean and numeric scores. Boolean score values must equal either 1 or 0 (true or false)
      comment: optional<string>
      metadata: optional<unknown>
      dataType:
        type: optional<commons.ScoreDataType>
        docs: When set, must match the score value's type. If not set, will be inferred from the score value or config
      configId:
        type: optional<string>
        docs: Reference a score config on a score. When set, the score name must equal the config name and scores must comply with the config's range and data type. For categorical scores, the value must map to a config category. Numeric scores might be constrained by the score config's max and min values
    examples:
      - value:
          name: "novelty"
          value: 0.9
          traceId: "cdef-1234-5678-90ab"
      - value:
          name: "consistency"
          value: 1.2
          dataType: "NUMERIC"
          traceId: "cdef-1234-5678-90ab"
      - value:
          name: "accuracy"
          value: 0.9
          dataType: "NUMERIC"
          configId: "9203-4567-89ab-cdef"
          traceId: "cdef-1234-5678-90ab"
      - value:
          name: "toxicity"
          value: "not toxic"
          traceId: "cdef-1234-5678-90ab"
      - value:
          name: "correctness"
          value: "partially correct"
          dataType: "CATEGORICAL"
          configId: "1234-5678-90ab-cdef"
          traceId: "cdef-1234-5678-90ab"
      - value:
          name: "hallucination"
          value: 0
          dataType: "BOOLEAN"
          traceId: "cdef-1234-5678-90ab"
      - value:
          name: "helpfulness"
          value: 1
          dataType: "BOOLEAN"
          configId: "1234-5678-90ab-cdef"
          traceId: "cdef-1234-5678-90ab"
      - value:
          name: "contextrelevant"
          value: "not relevant"
          sessionId: "abyt-1234-5678-80ab"
      - value:
          name: "hallucination"
          value: 0
          datasetRunId: "7891-5678-90ab-hijk"

  BaseEvent:
    properties:
      id:
        type: string
        docs: UUID v4 that identifies the event
      timestamp:
        type: string
        docs: "Datetime (ISO 8601) of event creation in client. Should be as close to actual event creation in client as possible, this timestamp will be used for ordering of events in future release. Resolution: milliseconds (required), microseconds (optimal)."
      metadata:
        type: optional<unknown>
        docs: Optional. Metadata field used by the Langfuse SDKs for debugging.

  TraceEvent:
    extends: BaseEvent
    properties:
      body: TraceBody

  CreateObservationEvent:
    extends: BaseEvent
    properties:
      body: ObservationBody

  UpdateObservationEvent:
    extends: BaseEvent
    properties:
      body: ObservationBody

  ScoreEvent:
    extends: BaseEvent
    properties:
      body: ScoreBody

  SDKLogEvent:
    extends: BaseEvent
    properties:
      body: SDKLogBody

  CreateGenerationEvent:
    extends: BaseEvent
    properties:
      body: CreateGenerationBody

  UpdateGenerationEvent:
    extends: BaseEvent
    properties:
      body: UpdateGenerationBody

  CreateSpanEvent:
    extends: BaseEvent
    properties:
      body: CreateSpanBody

  UpdateSpanEvent:
    extends: BaseEvent
    properties:
      body: UpdateSpanBody

  CreateEventEvent:
    extends: BaseEvent
    properties:
      body: CreateEventBody

  IngestionSuccess:
    properties:
      id: string
      status: integer

  IngestionError:
    properties:
      id: string
      status: integer
      message: optional<string>
      error: optional<unknown>

  IngestionResponse:
    properties:
      successes: list<IngestionSuccess>
      errors: list<IngestionError>

  OpenAICompletionUsageSchema:
    docs: OpenAI Usage schema from (Chat-)Completion APIs
    properties:
      prompt_tokens: integer
      completion_tokens: integer
      total_tokens: integer
      prompt_tokens_details: optional<map<string, optional<integer>>>
      completion_tokens_details: optional<map<string, optional<integer>>>

  OpenAIResponseUsageSchema:
    docs: OpenAI Usage schema from Response API
    properties:
      input_tokens: integer
      output_tokens: integer
      total_tokens: integer
      input_tokens_details: optional<map<string, optional<integer>>>
      output_tokens_details: optional<map<string, optional<integer>>>

  UsageDetails:
    discriminated: false
    union:
      - map<string, integer>
      - OpenAICompletionUsageSchema
      - OpenAIResponseUsageSchema
