{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://raw.githubusercontent.com/api-evangelist/latitude-so/main/json-schema/latitude-so-span-detail-schema.json",
  "title": "SpanDetail",
  "x-generated": "2026-10-18",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/latitude-so-openapi.json#/components/schemas/SpanDetail",
  "type": "object",
  "properties": {
    "organizationId": {
      "type": "string",
      "description": "Organization that owns this span."
    },
    "projectId": {
      "type": "string",
      "description": "Project this span belongs to."
    },
    "traceId": {
      "type": "string",
      "description": "Identifier of the trace this span belongs to."
    },
    "spanId": {
      "type": "string",
      "description": "Stable span identifier within the trace."
    },
    "parentSpanId": {
      "type": [
        "string",
        "null"
      ],
      "description": "Identifier of the parent span. `null` for root spans."
    },
    "sessionId": {
      "type": [
        "string",
        "null"
      ],
      "description": "Conversation/session identifier set by the SDK. `null` when absent."
    },
    "userId": {
      "type": [
        "string",
        "null"
      ],
      "description": "End-user identifier set by the SDK. `null` when absent."
    },
    "simulationId": {
      "type": [
        "string",
        "null"
      ],
      "description": "CUID of the simulation that produced this span. `null` when not a simulation."
    },
    "apiKeyId": {
      "type": [
        "string",
        "null"
      ],
      "description": "Latitude API key used to ingest the span. `null` when ingested without an API key."
    },
    "startTime": {
      "type": "string",
      "description": "ISO-8601 timestamp at which the span started."
    },
    "endTime": {
      "type": "string",
      "description": "ISO-8601 timestamp at which the span ended."
    },
    "name": {
      "type": "string",
      "description": "Span name (e.g. the entry-point function or route)."
    },
    "serviceName": {
      "type": "string",
      "description": "OpenTelemetry `service.name` of the emitting service."
    },
    "kind": {
      "type": "string",
      "enum": [
        "unspecified",
        "internal",
        "server",
        "client",
        "producer",
        "consumer"
      ],
      "description": "OpenTelemetry span kind."
    },
    "statusCode": {
      "type": "string",
      "enum": [
        "unset",
        "ok",
        "error"
      ],
      "description": "OpenTelemetry span status code."
    },
    "statusMessage": {
      "type": "string",
      "description": "OpenTelemetry status message. Empty when not set."
    },
    "traceFlags": {
      "type": "number",
      "description": "OpenTelemetry trace flags bitfield."
    },
    "traceState": {
      "type": "string",
      "description": "OpenTelemetry trace state (vendor-specific propagation). Empty when not set."
    },
    "errorType": {
      "type": [
        "string",
        "null"
      ],
      "description": "Error class/type label when the span errored. `null` for successful spans."
    },
    "tags": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Free-form tags attached at ingest time."
    },
    "operation": {
      "type": "string",
      "description": "GenAI operation category (e.g. `\"chat\"`, `\"embeddings\"`, `\"execute_tool\"`, `\"invoke_agent\"`) or a custom string for non-GenAI spans."
    },
    "provider": {
      "type": [
        "string",
        "null"
      ],
      "description": "LLM provider id. `null` for non-LLM spans."
    },
    "model": {
      "type": [
        "string",
        "null"
      ],
      "description": "Model id as requested. `null` for non-LLM spans."
    },
    "responseModel": {
      "type": [
        "string",
        "null"
      ],
      "description": "Model id reported by the provider's response. `null` for non-LLM spans."
    },
    "tokensInput": {
      "type": "number",
      "description": "Input tokens consumed by this span."
    },
    "tokensOutput": {
      "type": "number",
      "description": "Output tokens produced by this span."
    },
    "tokensCacheRead": {
      "type": "number",
      "description": "Tokens served from the provider's prompt cache."
    },
    "tokensCacheCreate": {
      "type": "number",
      "description": "Tokens written to the provider's prompt cache."
    },
    "tokensReasoning": {
      "type": "number",
      "description": "Reasoning tokens reported by the model."
    },
    "costInputMicrocents": {
      "type": "number",
      "description": "Cost of input tokens in microcents (100,000,000 per USD)."
    },
    "costOutputMicrocents": {
      "type": "number",
      "description": "Cost of output tokens in microcents (100,000,000 per USD)."
    },
    "costTotalMicrocents": {
      "type": "number",
      "description": "Total cost in microcents (100,000,000 per USD)."
    },
    "costIsEstimated": {
      "type": "boolean",
      "description": "`true` when the cost was derived from public pricing tables instead of the provider's bill."
    },
    "costSource": {
      "type": "string",
      "enum": [
        "provider_reported",
        "user_reported",
        "estimated",
        "unpriced",
        "no_tokens",
        "unknown"
      ],
      "description": "Where the cost came from. `provider_reported`: the instrumentation sent it. `user_reported`: you sent it with `latitude.cost.source` set to `user`. `estimated`: priced from public model pricing. `unpriced`: tokens were reported but no pricing matched, so the cost is 0 but not free. `no_tokens`: nothing to price. `unknown`: ingested before cost sources were tracked, so a 0 cannot be read as free."
    },
    "timeToFirstTokenNs": {
      "type": "number",
      "description": "Nanoseconds from the start of the span to its first emitted token. `0` if not measured."
    },
    "isStreaming": {
      "type": "boolean",
      "description": "`true` when the span was produced by a streaming LLM call."
    },
    "responseId": {
      "type": [
        "string",
        "null"
      ],
      "description": "Response identifier returned by the LLM. `null` when the provider didn't return one."
    },
    "finishReasons": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Per-choice finish reasons reported by the LLM provider."
    },
    "scopeName": {
      "type": "string",
      "description": "OpenTelemetry instrumentation scope name. Empty when not set."
    },
    "scopeVersion": {
      "type": "string",
      "description": "OpenTelemetry instrumentation scope version. Empty when not set."
    },
    "retentionDays": {
      "type": "integer",
      "minimum": 0,
      "exclusiveMinimum": true,
      "description": "Per-span retention override in days. Omitted when the project default applies."
    },
    "ingestedAt": {
      "type": "string",
      "description": "ISO-8601 timestamp at which Latitude received this span."
    },
    "metadata": {
      "type": "object",
      "additionalProperties": {
        "type": "string"
      },
      "description": "Free-form metadata attached at ingest time."
    },
    "systemInstructions": {
      "$ref": "#/$defs/GenAISpanSystem"
    },
    "inputMessages": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/GenAISpanMessage"
      },
      "description": "Input messages sent into this LLM span, in OpenTelemetry GenAI format."
    },
    "outputMessages": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/GenAISpanMessage"
      },
      "description": "Output messages returned by this LLM span, in OpenTelemetry GenAI format."
    },
    "toolDefinitions": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/ToolDefinition"
      },
      "description": "Tool/function definitions made available to the LLM for this span."
    },
    "toolCallId": {
      "type": "string",
      "description": "Tool-call id this span answers. Empty when the span isn't an `execute_tool` span."
    },
    "toolName": {
      "type": "string",
      "description": "Name of the executed tool. Empty when the span isn't an `execute_tool` span."
    },
    "toolInput": {
      "type": "string",
      "description": "Stringified arguments passed to the tool. Empty when the span isn't an `execute_tool` span."
    },
    "toolOutput": {
      "type": "string",
      "description": "Stringified tool output. Empty when the span isn't an `execute_tool` span."
    },
    "attrString": {
      "type": "object",
      "additionalProperties": {
        "type": "string"
      },
      "description": "OpenTelemetry attributes with string values."
    },
    "attrInt": {
      "type": "object",
      "additionalProperties": {
        "type": "number"
      },
      "description": "OpenTelemetry attributes with integer values."
    },
    "attrFloat": {
      "type": "object",
      "additionalProperties": {
        "type": "number"
      },
      "description": "OpenTelemetry attributes with floating-point values."
    },
    "attrBool": {
      "type": "object",
      "additionalProperties": {
        "type": "boolean"
      },
      "description": "OpenTelemetry attributes with boolean values."
    },
    "resourceString": {
      "type": "object",
      "additionalProperties": {
        "type": "string"
      },
      "description": "OpenTelemetry resource attributes captured at ingest."
    },
    "eventsJson": {
      "type": "string",
      "description": "JSON-encoded OpenTelemetry events array. Empty when the span has no events."
    },
    "linksJson": {
      "type": "string",
      "description": "JSON-encoded OpenTelemetry span-links array. Empty when the span has no links."
    }
  },
  "required": [
    "organizationId",
    "projectId",
    "traceId",
    "spanId",
    "parentSpanId",
    "sessionId",
    "userId",
    "simulationId",
    "apiKeyId",
    "startTime",
    "endTime",
    "name",
    "serviceName",
    "kind",
    "statusCode",
    "statusMessage",
    "traceFlags",
    "traceState",
    "errorType",
    "tags",
    "operation",
    "provider",
    "model",
    "responseModel",
    "tokensInput",
    "tokensOutput",
    "tokensCacheRead",
    "tokensCacheCreate",
    "tokensReasoning",
    "costInputMicrocents",
    "costOutputMicrocents",
    "costTotalMicrocents",
    "costIsEstimated",
    "costSource",
    "timeToFirstTokenNs",
    "isStreaming",
    "responseId",
    "finishReasons",
    "scopeName",
    "scopeVersion",
    "ingestedAt",
    "metadata",
    "systemInstructions",
    "inputMessages",
    "outputMessages",
    "toolDefinitions",
    "toolCallId",
    "toolName",
    "toolInput",
    "toolOutput",
    "attrString",
    "attrInt",
    "attrFloat",
    "attrBool",
    "resourceString",
    "eventsJson",
    "linksJson"
  ],
  "$defs": {
    "GenAISpanMessage": {
      "type": "object",
      "additionalProperties": {
        "nullable": true
      },
      "description": "Message in OpenTelemetry GenAI format (`role` + content parts + optional tool calls)."
    },
    "GenAISpanSystem": {
      "type": "array",
      "items": {
        "type": "object",
        "additionalProperties": {
          "nullable": true
        }
      },
      "description": "System instructions in OpenTelemetry GenAI format — an array of part objects."
    },
    "ToolDefinition": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string",
          "description": "Tool name as exposed to the LLM."
        },
        "description": {
          "type": "string",
          "description": "Tool description as exposed to the LLM."
        },
        "parameters": {
          "nullable": true,
          "description": "JSON Schema for the tool's parameters, as provided by the caller."
        }
      },
      "required": [
        "name",
        "description"
      ]
    }
  }
}