From fab9bf05db539bcf095ac05843cd0456a517fb62 Mon Sep 17 00:00:00 2001
From: ScriptSmith <ScriptSmith@users.noreply.github.com>
Date: Sun, 29 Mar 2026 16:54:38 +1000
Subject: [PATCH 1/8] Changes for OpenResponses spec compliance

---
 src/api_types/responses.rs         | 218 +++++++++++++++++++++++++----
 src/providers/anthropic/convert.rs |   3 +
 src/providers/anthropic/mod.rs     |   6 +-
 src/providers/anthropic/stream.rs  |  86 +++++++-----
 src/providers/bedrock/convert.rs   |   3 +
 src/providers/bedrock/mod.rs       |  12 +-
 src/providers/bedrock/stream.rs    |  95 ++++++++-----
 src/providers/vertex/convert.rs    |   3 +
 src/providers/vertex/mod.rs        |  11 +-
 src/providers/vertex/stream.rs     |  86 ++++++++----
 src/services/file_search_tool.rs   |  14 ++
 11 files changed, 402 insertions(+), 135 deletions(-)

diff --git a/src/api_types/responses.rs b/src/api_types/responses.rs
index b296d244..391eb63e 100644
--- a/src/api_types/responses.rs
+++ b/src/api_types/responses.rs
@@ -19,9 +19,10 @@ where
 }
 use validator::Validate;
 
-#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
+#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
 #[serde(rename_all = "snake_case")]
 pub enum ResponseInputImageDetail {
+    #[default]
     Auto,
     High,
     Low,
@@ -268,6 +269,7 @@ pub enum ResponseInputContentItem {
         cache_control: Option<CacheControl>,
     },
     InputImage {
+        #[serde(default)]
         detail: ResponseInputImageDetail,
         #[serde(skip_serializing_if = "Option::is_none")]
         image_url: Option<String>,
@@ -530,9 +532,9 @@ pub enum ResponsesAnnotation {
 pub enum OutputMessageContentItem {
     OutputText {
         text: String,
-        #[serde(default, skip_serializing_if = "Vec::is_empty")]
+        #[serde(default)]
         annotations: Vec<ResponsesAnnotation>,
-        #[serde(default, skip_serializing_if = "Vec::is_empty")]
+        #[serde(default)]
         logprobs: Vec<serde_json::Value>,
     },
     Refusal {
@@ -1332,6 +1334,16 @@ pub struct CreateResponsesPayload {
     #[cfg_attr(feature = "utoipa", schema(value_type = Object))]
     pub truncation: Option<serde_json::Value>,
 
+    /// Presence penalty (-2.0 to 2.0)
+    #[validate(range(min = -2.0, max = 2.0))]
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub presence_penalty: Option<f64>,
+
+    /// Frequency penalty (-2.0 to 2.0)
+    #[validate(range(min = -2.0, max = 2.0))]
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub frequency_penalty: Option<f64>,
+
     /// Enable streaming
     #[serde(default)]
     pub stream: bool,
@@ -1428,53 +1440,207 @@ pub struct CreateResponsesResponse {
     pub user: Option<String>,
     #[serde(skip_serializing_if = "Option::is_none")]
     pub output_text: Option<String>,
-    #[serde(skip_serializing_if = "Option::is_none")]
     pub prompt_cache_key: Option<String>,
-    #[serde(skip_serializing_if = "Option::is_none")]
     pub safety_identifier: Option<String>,
-    #[serde(skip_serializing_if = "Option::is_none")]
     pub error: Option<ResponsesErrorField>,
-    #[serde(skip_serializing_if = "Option::is_none")]
     pub incomplete_details: Option<ResponsesIncompleteDetails>,
     #[serde(skip_serializing_if = "Option::is_none")]
     pub usage: Option<ResponsesUsage>,
-    #[serde(skip_serializing_if = "Option::is_none")]
+    pub completed_at: Option<f64>,
     pub max_tool_calls: Option<f64>,
-    #[serde(skip_serializing_if = "Option::is_none")]
     pub top_logprobs: Option<f64>,
-    #[serde(
-        skip_serializing_if = "Option::is_none",
-        serialize_with = "serialize_as_integer"
-    )]
+    #[serde(serialize_with = "serialize_as_integer")]
     pub max_output_tokens: Option<f64>,
-    #[serde(skip_serializing_if = "Option::is_none")]
     pub temperature: Option<f64>,
-    #[serde(skip_serializing_if = "Option::is_none")]
     pub top_p: Option<f64>,
-    #[serde(skip_serializing_if = "Option::is_none")]
+    pub presence_penalty: Option<f64>,
+    pub frequency_penalty: Option<f64>,
     pub instructions: Option<serde_json::Value>,
     #[serde(skip_serializing_if = "Option::is_none")]
     pub metadata: Option<HashMap<String, String>>,
-    #[serde(default, skip_serializing_if = "Option::is_none")]
     pub tools: Option<Vec<ResponsesToolDefinition>>,
-    #[serde(skip_serializing_if = "Option::is_none")]
     pub tool_choice: Option<ResponsesToolChoice>,
-    #[serde(skip_serializing_if = "Option::is_none")]
     pub parallel_tool_calls: Option<bool>,
     #[serde(skip_serializing_if = "Option::is_none")]
     pub prompt: Option<ResponsesPrompt>,
-    #[serde(skip_serializing_if = "Option::is_none")]
     pub background: Option<bool>,
-    #[serde(skip_serializing_if = "Option::is_none")]
     pub previous_response_id: Option<String>,
-    #[serde(skip_serializing_if = "Option::is_none")]
     pub reasoning: Option<ResponsesReasoningConfigOutput>,
-    #[serde(skip_serializing_if = "Option::is_none")]
     pub service_tier: Option<ResponsesServiceTier>,
-    #[serde(skip_serializing_if = "Option::is_none")]
     pub store: Option<bool>,
-    #[serde(skip_serializing_if = "Option::is_none")]
     pub truncation: Option<ResponsesTruncation>,
-    #[serde(skip_serializing_if = "Option::is_none")]
     pub text: Option<ResponseTextConfig>,
 }
+
+impl CreateResponsesResponse {
+    /// Serialize to JSON with echo fields merged in per OpenAI Responses API spec.
+    pub fn to_json_with_echo(
+        &self,
+        echo_fields: serde_json::Map<String, serde_json::Value>,
+    ) -> serde_json::Value {
+        let mut val = serde_json::to_value(self).unwrap_or_default();
+        if let serde_json::Value::Object(ref mut map) = val {
+            if self.status == Some(ResponsesResponseStatus::Completed) {
+                map.insert("completed_at".into(), serde_json::json!(self.created_at));
+            }
+            for (k, v) in echo_fields {
+                // Don't overwrite reasoning if the struct already has it set from conversion
+                if k == "reasoning" && self.reasoning.is_some() {
+                    continue;
+                }
+                map.insert(k, v);
+            }
+        }
+        val
+    }
+}
+
+impl CreateResponsesPayload {
+    /// Produce a JSON map of echo fields for streaming response.completed events.
+    pub fn echo_fields_json(&self) -> serde_json::Map<String, serde_json::Value> {
+        let mut m = serde_json::Map::new();
+
+        // Echo tools with required fields (strict, description) filled in
+        let tools_json =
+            serde_json::to_value(self.tools.clone().unwrap_or_default()).unwrap_or_default();
+        let tools_json = if let serde_json::Value::Array(tools) = tools_json {
+            serde_json::Value::Array(
+                tools
+                    .into_iter()
+                    .map(|mut t| {
+                        if let serde_json::Value::Object(ref mut obj) = t {
+                            obj.entry("strict").or_insert(serde_json::Value::Null);
+                            obj.entry("description").or_insert(serde_json::Value::Null);
+                        }
+                        t
+                    })
+                    .collect(),
+            )
+        } else {
+            tools_json
+        };
+        m.insert("tools".into(), tools_json);
+        m.insert(
+            "tool_choice".into(),
+            serde_json::to_value(
+                self.tool_choice
+                    .clone()
+                    .unwrap_or(ResponsesToolChoice::String(
+                        ResponsesToolChoiceDefault::Auto,
+                    )),
+            )
+            .unwrap_or_default(),
+        );
+        m.insert(
+            "parallel_tool_calls".into(),
+            serde_json::Value::Bool(self.parallel_tool_calls.unwrap_or(true)),
+        );
+        m.insert(
+            "temperature".into(),
+            serde_json::json!(self.temperature.unwrap_or(1.0)),
+        );
+        m.insert("top_p".into(), serde_json::json!(self.top_p.unwrap_or(1.0)));
+        m.insert(
+            "store".into(),
+            serde_json::Value::Bool(self.store.unwrap_or(true)),
+        );
+        m.insert(
+            "background".into(),
+            serde_json::Value::Bool(self.background.unwrap_or(false)),
+        );
+        m.insert(
+            "truncation".into(),
+            serde_json::to_value(
+                self.truncation
+                    .as_ref()
+                    .and_then(|v| serde_json::from_value::<ResponsesTruncation>(v.clone()).ok())
+                    .unwrap_or(ResponsesTruncation::Disabled),
+            )
+            .unwrap_or_default(),
+        );
+        m.insert(
+            "text".into(),
+            serde_json::to_value(self.text.clone().unwrap_or(ResponseTextConfig {
+                format: Some(ResponseFormatTextConfig::Text),
+                verbosity: None,
+            }))
+            .unwrap_or_default(),
+        );
+        m.insert(
+            "service_tier".into(),
+            serde_json::to_value(
+                self.service_tier
+                    .as_ref()
+                    .and_then(|v| serde_json::from_value::<ResponsesServiceTier>(v.clone()).ok())
+                    .unwrap_or(ResponsesServiceTier::Default),
+            )
+            .unwrap_or_default(),
+        );
+        m.insert(
+            "presence_penalty".into(),
+            serde_json::json!(self.presence_penalty.unwrap_or(0.0)),
+        );
+        m.insert(
+            "frequency_penalty".into(),
+            serde_json::json!(self.frequency_penalty.unwrap_or(0.0)),
+        );
+        m.insert(
+            "instructions".into(),
+            self.instructions
+                .as_ref()
+                .map(|s| serde_json::Value::String(s.clone()))
+                .unwrap_or(serde_json::Value::Null),
+        );
+        m.insert(
+            "previous_response_id".into(),
+            self.previous_response_id
+                .as_ref()
+                .map(|s| serde_json::Value::String(s.clone()))
+                .unwrap_or(serde_json::Value::Null),
+        );
+        m.insert(
+            "prompt_cache_key".into(),
+            self.prompt_cache_key
+                .as_ref()
+                .map(|s| serde_json::Value::String(s.clone()))
+                .unwrap_or(serde_json::Value::Null),
+        );
+        m.insert(
+            "safety_identifier".into(),
+            self.safety_identifier
+                .as_ref()
+                .map(|s| serde_json::Value::String(s.clone()))
+                .unwrap_or(serde_json::Value::Null),
+        );
+        m.insert(
+            "max_output_tokens".into(),
+            self.max_output_tokens
+                .map(|v| {
+                    if v.fract() == 0.0 {
+                        serde_json::json!(v as i64)
+                    } else {
+                        serde_json::json!(v)
+                    }
+                })
+                .unwrap_or(serde_json::Value::Null),
+        );
+        m.insert("error".into(), serde_json::Value::Null);
+        m.insert("incomplete_details".into(), serde_json::Value::Null);
+        m.insert("max_tool_calls".into(), serde_json::Value::Null);
+        m.insert("top_logprobs".into(), serde_json::json!(0));
+        // Ensure reasoning is echoed (null if not configured)
+        m.insert(
+            "reasoning".into(),
+            self.reasoning
+                .as_ref()
+                .map(|r| {
+                    serde_json::json!({
+                        "effort": r.effort.as_ref().map(|e| serde_json::to_value(e).unwrap_or_default()),
+                        "summary": r.summary.as_ref().map(|s| serde_json::to_value(s).unwrap_or_default()),
+                    })
+                })
+                .unwrap_or(serde_json::Value::Null),
+        );
+        m
+    }
+}
diff --git a/src/providers/anthropic/convert.rs b/src/providers/anthropic/convert.rs
index 918c3028..3650f994 100644
--- a/src/providers/anthropic/convert.rs
+++ b/src/providers/anthropic/convert.rs
@@ -1050,11 +1050,14 @@ pub fn convert_anthropic_to_responses_response(
             is_byok: None,
             cost_details: None,
         }),
+        completed_at: None,
         max_tool_calls: None,
         top_logprobs: None,
         max_output_tokens: None,
         temperature: None,
         top_p: None,
+        presence_penalty: None,
+        frequency_penalty: None,
         instructions: None,
         metadata: None,
         tools: None,
diff --git a/src/providers/anthropic/mod.rs b/src/providers/anthropic/mod.rs
index b72eccb7..39898a82 100644
--- a/src/providers/anthropic/mod.rs
+++ b/src/providers/anthropic/mod.rs
@@ -291,6 +291,8 @@ impl Provider for AnthropicProvider {
             .or(self.default_max_tokens)
             .unwrap_or(DEFAULT_MAX_TOKENS);
 
+        let echo_fields = payload.echo_fields_json();
+
         // Convert Responses API input to Anthropic messages format
         let (system, messages) =
             convert_responses_input_to_messages(payload.input, payload.instructions.clone());
@@ -384,7 +386,7 @@ impl Provider for AnthropicProvider {
                         result.map_err(std::io::Error::other)
                     });
             let transformed_stream =
-                AnthropicToResponsesStream::new(byte_stream, &self.streaming_buffer);
+                AnthropicToResponsesStream::new(byte_stream, &self.streaming_buffer, echo_fields);
 
             #[cfg(not(target_arch = "wasm32"))]
             {
@@ -401,7 +403,7 @@ impl Provider for AnthropicProvider {
                 payload.reasoning.as_ref(),
                 payload.user,
             );
-            json_response(status, &responses_response)
+            json_response(status, &responses_response.to_json_with_echo(echo_fields))
         }
     }
 
diff --git a/src/providers/anthropic/stream.rs b/src/providers/anthropic/stream.rs
index fad94180..db44fd58 100644
--- a/src/providers/anthropic/stream.rs
+++ b/src/providers/anthropic/stream.rs
@@ -703,6 +703,8 @@ struct ResponsesStreamState {
     stop_reason: Option<String>,
     /// Sequence number for Responses API events
     sequence_number: i32,
+    /// Echo fields from request payload for response.completed
+    echo_fields: serde_json::Map<String, serde_json::Value>,
 }
 
 /// Stream transformer that converts Anthropic SSE to OpenAI Responses API SSE format
@@ -718,10 +720,17 @@ pub struct AnthropicToResponsesStream<S> {
 }
 
 impl<S> AnthropicToResponsesStream<S> {
-    pub fn new(inner: S, streaming_buffer: &StreamingBufferConfig) -> Self {
+    pub fn new(
+        inner: S,
+        streaming_buffer: &StreamingBufferConfig,
+        echo_fields: serde_json::Map<String, serde_json::Value>,
+    ) -> Self {
         Self {
             inner,
-            state: ResponsesStreamState::default(),
+            state: ResponsesStreamState {
+                echo_fields,
+                ..ResponsesStreamState::default()
+            },
             output_buffer: Vec::new(),
             max_input_buffer_bytes: streaming_buffer.max_input_buffer_bytes,
             max_output_buffer_chunks: streaming_buffer.max_output_buffer_chunks,
@@ -738,6 +747,30 @@ impl<S> AnthropicToResponsesStream<S> {
         seq
     }
 
+    /// Build a response JSON object with echo fields for streaming events.
+    fn build_response_json(
+        &self,
+        status: &str,
+        output: serde_json::Value,
+    ) -> serde_json::Map<String, serde_json::Value> {
+        let mut obj = serde_json::Map::new();
+        obj.insert("id".into(), serde_json::json!(self.state.response_id));
+        obj.insert("object".into(), serde_json::json!("response"));
+        obj.insert(
+            "created_at".into(),
+            serde_json::json!(Self::created_timestamp()),
+        );
+        obj.insert("model".into(), serde_json::json!(self.state.model));
+        obj.insert("status".into(), serde_json::json!(status));
+        obj.insert("output".into(), output);
+        obj.insert("completed_at".into(), serde_json::Value::Null);
+        obj.insert("usage".into(), serde_json::Value::Null);
+        for (k, v) in &self.state.echo_fields {
+            obj.insert(k.clone(), v.clone());
+        }
+        obj
+    }
+
     /// Calculate the output index for message (accounting for reasoning if present)
     fn message_output_index(&self) -> usize {
         if self.state.emitted_reasoning_added {
@@ -810,19 +843,8 @@ impl<S> AnthropicToResponsesStream<S> {
                 // Emit response.created
                 if !self.state.emitted_response_created {
                     self.state.emitted_response_created = true;
-                    self.emit_event(
-                        "response.created",
-                        serde_json::json!({
-                            "response": {
-                                "id": self.state.response_id,
-                                "object": "response",
-                                "created_at": Self::created_timestamp(),
-                                "model": self.state.model,
-                                "status": "in_progress",
-                                "output": []
-                            }
-                        }),
-                    );
+                    let resp = self.build_response_json("in_progress", serde_json::json!([]));
+                    self.emit_event("response.created", serde_json::json!({ "response": resp }));
                 }
             }
 
@@ -1219,26 +1241,26 @@ impl<S> AnthropicToResponsesStream<S> {
                     _ => "completed",
                 };
 
+                // Build response object with echo fields
+                let mut response_obj = self.build_response_json(status, serde_json::json!(output));
+                response_obj.insert("usage".into(), serde_json::json!({
+                    "input_tokens": self.state.input_tokens,
+                    "input_tokens_details": { "cached_tokens": self.state.cache_read_input_tokens },
+                    "output_tokens": self.state.output_tokens,
+                    "output_tokens_details": { "reasoning_tokens": 0 },
+                    "total_tokens": self.state.input_tokens + self.state.output_tokens
+                }));
+                if status == "completed" {
+                    response_obj.insert(
+                        "completed_at".into(),
+                        serde_json::json!(Self::created_timestamp()),
+                    );
+                }
+
                 // Emit response.completed
                 self.emit_event(
                     "response.completed",
-                    serde_json::json!({
-                        "response": {
-                            "id": self.state.response_id,
-                            "object": "response",
-                            "created_at": Self::created_timestamp(),
-                            "model": self.state.model,
-                            "status": status,
-                            "output": output,
-                            "usage": {
-                                "input_tokens": self.state.input_tokens,
-                                "input_tokens_details": { "cached_tokens": self.state.cache_read_input_tokens },
-                                "output_tokens": self.state.output_tokens,
-                                "output_tokens_details": { "reasoning_tokens": 0 },
-                                "total_tokens": self.state.input_tokens + self.state.output_tokens
-                            }
-                        }
-                    }),
+                    serde_json::json!({ "response": response_obj }),
                 );
 
                 // Emit [DONE] to signal end of stream (OpenAI Responses API convention)
diff --git a/src/providers/bedrock/convert.rs b/src/providers/bedrock/convert.rs
index c239e3c9..67ebc9a5 100644
--- a/src/providers/bedrock/convert.rs
+++ b/src/providers/bedrock/convert.rs
@@ -927,11 +927,14 @@ pub(super) fn convert_bedrock_to_responses_response(
             is_byok: None,
             cost_details: None,
         }),
+        completed_at: None,
         max_tool_calls: None,
         top_logprobs: None,
         max_output_tokens: None,
         temperature: None,
         top_p: None,
+        presence_penalty: None,
+        frequency_penalty: None,
         instructions: None,
         metadata: None,
         tools: None,
diff --git a/src/providers/bedrock/mod.rs b/src/providers/bedrock/mod.rs
index dcbdafea..c3d53227 100644
--- a/src/providers/bedrock/mod.rs
+++ b/src/providers/bedrock/mod.rs
@@ -684,6 +684,8 @@ impl Provider for BedrockProvider {
             .clone()
             .unwrap_or_else(|| "anthropic.claude-3-sonnet-20240229-v1:0".to_string());
 
+        let echo_fields = payload.echo_fields_json();
+
         // Convert Responses API input to Bedrock Converse format
         let (system, messages) =
             convert_responses_input_to_bedrock_messages(payload.input, payload.instructions);
@@ -757,8 +759,12 @@ impl Provider for BedrockProvider {
             }
 
             let byte_stream = response.bytes_stream();
-            let transformed_stream =
-                BedrockToResponsesStream::new(byte_stream, model, &self.streaming_buffer);
+            let transformed_stream = BedrockToResponsesStream::new(
+                byte_stream,
+                model,
+                &self.streaming_buffer,
+                echo_fields,
+            );
 
             return streaming_response(status, transformed_stream);
         }
@@ -797,7 +803,7 @@ impl Provider for BedrockProvider {
             payload.reasoning.as_ref(),
             payload.user,
         );
-        json_response(status, &responses_response)
+        json_response(status, &responses_response.to_json_with_echo(echo_fields))
     }
 
     #[tracing::instrument(
diff --git a/src/providers/bedrock/stream.rs b/src/providers/bedrock/stream.rs
index 53b27332..296c9e4f 100644
--- a/src/providers/bedrock/stream.rs
+++ b/src/providers/bedrock/stream.rs
@@ -531,6 +531,8 @@ pub(super) struct ResponsesStreamState {
     pub reasoning_id: String,
     /// Whether we've emitted the output_item.added for reasoning
     pub emitted_reasoning_added: bool,
+    /// Echo fields from request payload for response.completed
+    pub echo_fields: serde_json::Map<String, serde_json::Value>,
 }
 
 /// Stream transformer that converts Bedrock event stream to OpenAI Responses API SSE format
@@ -546,7 +548,12 @@ pub struct BedrockToResponsesStream<S> {
 }
 
 impl<S> BedrockToResponsesStream<S> {
-    pub fn new(inner: S, model: String, streaming_buffer: &StreamingBufferConfig) -> Self {
+    pub fn new(
+        inner: S,
+        model: String,
+        streaming_buffer: &StreamingBufferConfig,
+        echo_fields: serde_json::Map<String, serde_json::Value>,
+    ) -> Self {
         let response_id = format!("resp_{}", uuid::Uuid::new_v4().simple());
         let message_id = format!("msg_{}", uuid::Uuid::new_v4().simple());
         // Generate reasoning ID from response ID (similar to Anthropic pattern)
@@ -564,6 +571,7 @@ impl<S> BedrockToResponsesStream<S> {
                 model,
                 decoder: MessageFrameDecoder::new(),
                 buffer: bytes::BytesMut::new(),
+                echo_fields,
                 ..ResponsesStreamState::default()
             },
             output_buffer: Vec::new(),
@@ -582,6 +590,30 @@ impl<S> BedrockToResponsesStream<S> {
         seq
     }
 
+    /// Build a response JSON object with echo fields for streaming events.
+    fn build_response_json(
+        &self,
+        status: &str,
+        output: serde_json::Value,
+    ) -> serde_json::Map<String, serde_json::Value> {
+        let mut obj = serde_json::Map::new();
+        obj.insert("id".into(), serde_json::json!(self.state.response_id));
+        obj.insert("object".into(), serde_json::json!("response"));
+        obj.insert(
+            "created_at".into(),
+            serde_json::json!(Self::created_timestamp()),
+        );
+        obj.insert("model".into(), serde_json::json!(self.state.model));
+        obj.insert("status".into(), serde_json::json!(status));
+        obj.insert("output".into(), output);
+        obj.insert("completed_at".into(), serde_json::Value::Null);
+        obj.insert("usage".into(), serde_json::Value::Null);
+        for (k, v) in &self.state.echo_fields {
+            obj.insert(k.clone(), v.clone());
+        }
+        obj
+    }
+
     /// Calculate the output index for message (accounting for reasoning if present)
     fn message_output_index(&self) -> usize {
         if self.state.emitted_reasoning_added {
@@ -659,33 +691,17 @@ impl<S> BedrockToResponsesStream<S> {
                     // Emit response.created
                     if !self.state.emitted_response_created {
                         self.state.emitted_response_created = true;
+                        let resp = self.build_response_json("in_progress", serde_json::json!([]));
                         self.emit_event(
                             "response.created",
-                            serde_json::json!({
-                                "response": {
-                                    "id": self.state.response_id,
-                                    "object": "response",
-                                    "created_at": Self::created_timestamp(),
-                                    "model": self.state.model,
-                                    "status": "in_progress",
-                                    "output": []
-                                }
-                            }),
+                            serde_json::json!({ "response": resp }),
                         );
 
                         // Emit response.in_progress
+                        let resp = self.build_response_json("in_progress", serde_json::json!([]));
                         self.emit_event(
                             "response.in_progress",
-                            serde_json::json!({
-                                "response": {
-                                    "id": self.state.response_id,
-                                    "object": "response",
-                                    "created_at": Self::created_timestamp(),
-                                    "model": self.state.model,
-                                    "status": "in_progress",
-                                    "output": []
-                                }
-                            }),
+                            serde_json::json!({ "response": resp }),
                         );
                     }
                 }
@@ -1068,26 +1084,27 @@ impl<S> BedrockToResponsesStream<S> {
                         _ => "completed",
                     };
 
+                    // Build response object with echo fields
+                    let mut response_obj =
+                        self.build_response_json(status, serde_json::json!(output));
+                    response_obj.insert("usage".into(), serde_json::json!({
+                        "input_tokens": self.state.input_tokens,
+                        "input_tokens_details": { "cached_tokens": self.state.cache_read_input_tokens },
+                        "output_tokens": self.state.output_tokens,
+                        "output_tokens_details": { "reasoning_tokens": 0 },
+                        "total_tokens": self.state.input_tokens + self.state.output_tokens
+                    }));
+                    if status == "completed" {
+                        response_obj.insert(
+                            "completed_at".into(),
+                            serde_json::json!(Self::created_timestamp()),
+                        );
+                    }
+
                     // Emit response.completed
                     self.emit_event(
                         "response.completed",
-                        serde_json::json!({
-                            "response": {
-                                "id": self.state.response_id,
-                                "object": "response",
-                                "created_at": Self::created_timestamp(),
-                                "model": self.state.model,
-                                "status": status,
-                                "output": output,
-                                "usage": {
-                                    "input_tokens": self.state.input_tokens,
-                                    "input_tokens_details": { "cached_tokens": self.state.cache_read_input_tokens },
-                                    "output_tokens": self.state.output_tokens,
-                                    "output_tokens_details": { "reasoning_tokens": 0 },
-                                    "total_tokens": self.state.input_tokens + self.state.output_tokens
-                                }
-                            }
-                        }),
+                        serde_json::json!({ "response": response_obj }),
                     );
 
                     // Emit [DONE] to signal end of stream
@@ -1727,6 +1744,7 @@ mod streaming_tests {
             empty_stream,
             "test-model".into(),
             &StreamingBufferConfig::default(),
+            serde_json::Map::new(),
         )
     }
 
@@ -1852,6 +1870,7 @@ mod streaming_tests {
             byte_stream,
             "test-model".into(),
             &StreamingBufferConfig::default(),
+            serde_json::Map::new(),
         );
 
         let mut outputs = Vec::new();
diff --git a/src/providers/vertex/convert.rs b/src/providers/vertex/convert.rs
index d9aa743e..2de6a0c5 100644
--- a/src/providers/vertex/convert.rs
+++ b/src/providers/vertex/convert.rs
@@ -971,11 +971,14 @@ pub(super) fn convert_vertex_to_responses_response(
         error: None,
         incomplete_details: None,
         usage,
+        completed_at: None,
         max_tool_calls: None,
         top_logprobs: None,
         max_output_tokens: None,
         temperature: None,
         top_p: None,
+        presence_penalty: None,
+        frequency_penalty: None,
         instructions: None,
         metadata: None,
         tools: None,
diff --git a/src/providers/vertex/mod.rs b/src/providers/vertex/mod.rs
index 5b0e6b43..1f706532 100644
--- a/src/providers/vertex/mod.rs
+++ b/src/providers/vertex/mod.rs
@@ -463,6 +463,7 @@ impl Provider for VertexProvider {
             .unwrap_or_else(|| "gemini-2.0-flash".to_string());
 
         let stream = payload.stream;
+        let echo_fields = payload.echo_fields_json();
 
         // Convert Responses API input to Vertex format
         let (system_instruction, contents) =
@@ -536,8 +537,12 @@ impl Provider for VertexProvider {
             let byte_stream = response
                 .bytes_stream()
                 .map(|result| result.map_err(std::io::Error::other));
-            let transformed_stream =
-                VertexToResponsesStream::new(byte_stream, model, &self.streaming_buffer);
+            let transformed_stream = VertexToResponsesStream::new(
+                byte_stream,
+                model,
+                &self.streaming_buffer,
+                echo_fields,
+            );
 
             return streaming_response(status, transformed_stream);
         }
@@ -555,7 +560,7 @@ impl Provider for VertexProvider {
             payload.reasoning.as_ref(),
             payload.user,
         );
-        json_response(status, &responses_response)
+        json_response(status, &responses_response.to_json_with_echo(echo_fields))
     }
 
     #[tracing::instrument(
diff --git a/src/providers/vertex/stream.rs b/src/providers/vertex/stream.rs
index 25f6dfc3..401f85d9 100644
--- a/src/providers/vertex/stream.rs
+++ b/src/providers/vertex/stream.rs
@@ -508,6 +508,8 @@ pub(super) struct ResponsesStreamState {
     pub finish_reason: Option<String>,
     /// Sequence number for Responses API events
     pub sequence_number: i32,
+    /// Echo fields from request payload for response.completed
+    pub echo_fields: serde_json::Map<String, serde_json::Value>,
 }
 
 /// Stream transformer that converts Vertex SSE to OpenAI Responses API SSE format
@@ -523,7 +525,12 @@ pub struct VertexToResponsesStream<S> {
 }
 
 impl<S> VertexToResponsesStream<S> {
-    pub fn new(inner: S, model: String, streaming_buffer: &StreamingBufferConfig) -> Self {
+    pub fn new(
+        inner: S,
+        model: String,
+        streaming_buffer: &StreamingBufferConfig,
+        echo_fields: serde_json::Map<String, serde_json::Value>,
+    ) -> Self {
         Self {
             inner,
             state: ResponsesStreamState {
@@ -531,6 +538,7 @@ impl<S> VertexToResponsesStream<S> {
                 message_id: format!("msg_{}", uuid::Uuid::new_v4().simple()),
                 reasoning_id: format!("rs_{}", uuid::Uuid::new_v4().simple()),
                 model,
+                echo_fields,
                 ..ResponsesStreamState::default()
             },
             output_buffer: Vec::new(),
@@ -549,6 +557,30 @@ impl<S> VertexToResponsesStream<S> {
         seq
     }
 
+    /// Build a response JSON object with echo fields for streaming events.
+    fn build_response_json(
+        &self,
+        status: &str,
+        output: serde_json::Value,
+    ) -> serde_json::Map<String, serde_json::Value> {
+        let mut obj = serde_json::Map::new();
+        obj.insert("id".into(), serde_json::json!(self.state.response_id));
+        obj.insert("object".into(), serde_json::json!("response"));
+        obj.insert(
+            "created_at".into(),
+            serde_json::json!(Self::created_timestamp()),
+        );
+        obj.insert("model".into(), serde_json::json!(self.state.model));
+        obj.insert("status".into(), serde_json::json!(status));
+        obj.insert("output".into(), output);
+        obj.insert("completed_at".into(), serde_json::Value::Null);
+        obj.insert("usage".into(), serde_json::Value::Null);
+        for (k, v) in &self.state.echo_fields {
+            obj.insert(k.clone(), v.clone());
+        }
+        obj
+    }
+
     /// Parse a Vertex SSE line and generate Responses API SSE chunks
     fn process_sse_line(&mut self, line: &str) {
         // Vertex SSE format: "data: {json}"
@@ -582,19 +614,8 @@ impl<S> VertexToResponsesStream<S> {
         // Emit response.created on first chunk
         if !self.state.emitted_response_created {
             self.state.emitted_response_created = true;
-            self.emit_event(
-                "response.created",
-                serde_json::json!({
-                    "response": {
-                        "id": self.state.response_id,
-                        "object": "response",
-                        "created_at": Self::created_timestamp(),
-                        "model": self.state.model,
-                        "status": "in_progress",
-                        "output": []
-                    }
-                }),
-            );
+            let resp = self.build_response_json("in_progress", serde_json::json!([]));
+            self.emit_event("response.created", serde_json::json!({ "response": resp }));
         }
 
         // Update usage if available
@@ -962,26 +983,29 @@ impl<S> VertexToResponsesStream<S> {
             _ => "completed",
         };
 
+        // Build response object with echo fields
+        let mut response_obj = self.build_response_json(status, serde_json::json!(output));
+        response_obj.insert(
+            "usage".into(),
+            serde_json::json!({
+                "input_tokens": self.state.input_tokens,
+                "input_tokens_details": { "cached_tokens": 0 },
+                "output_tokens": self.state.output_tokens,
+                "output_tokens_details": { "reasoning_tokens": self.state.reasoning_tokens },
+                "total_tokens": self.state.input_tokens + self.state.output_tokens
+            }),
+        );
+        if status == "completed" {
+            response_obj.insert(
+                "completed_at".into(),
+                serde_json::json!(Self::created_timestamp()),
+            );
+        }
+
         // Emit response.completed with reasoning tokens in usage
         self.emit_event(
             "response.completed",
-            serde_json::json!({
-                "response": {
-                    "id": self.state.response_id,
-                    "object": "response",
-                    "created_at": Self::created_timestamp(),
-                    "model": self.state.model,
-                    "status": status,
-                    "output": output,
-                    "usage": {
-                        "input_tokens": self.state.input_tokens,
-                        "input_tokens_details": { "cached_tokens": 0 },
-                        "output_tokens": self.state.output_tokens,
-                        "output_tokens_details": { "reasoning_tokens": self.state.reasoning_tokens },
-                        "total_tokens": self.state.input_tokens + self.state.output_tokens
-                    }
-                }
-            }),
+            serde_json::json!({ "response": response_obj }),
         );
     }
 
diff --git a/src/services/file_search_tool.rs b/src/services/file_search_tool.rs
index 028f02ba..dc36d6d9 100644
--- a/src/services/file_search_tool.rs
+++ b/src/services/file_search_tool.rs
@@ -2318,6 +2318,8 @@ mod tests {
             store: None,
             service_tier: None,
             truncation: None,
+            presence_penalty: None,
+            frequency_penalty: None,
             stream: false,
             provider: None,
             plugins: None,
@@ -2455,6 +2457,8 @@ mod tests {
             store: None,
             service_tier: None,
             truncation: None,
+            presence_penalty: None,
+            frequency_penalty: None,
             stream: false,
             provider: None,
             plugins: None,
@@ -2541,6 +2545,8 @@ mod tests {
             store: None,
             service_tier: None,
             truncation: None,
+            presence_penalty: None,
+            frequency_penalty: None,
             stream: false,
             provider: None,
             plugins: None,
@@ -2617,6 +2623,8 @@ mod tests {
             store: None,
             service_tier: None,
             truncation: None,
+            presence_penalty: None,
+            frequency_penalty: None,
             stream: false,
             provider: None,
             plugins: None,
@@ -3350,6 +3358,8 @@ mod tests {
             store: None,
             service_tier: None,
             truncation: None,
+            presence_penalty: None,
+            frequency_penalty: None,
             stream: false,
             provider: None,
             plugins: None,
@@ -3399,6 +3409,8 @@ mod tests {
             store: None,
             service_tier: None,
             truncation: None,
+            presence_penalty: None,
+            frequency_penalty: None,
             stream: false,
             provider: None,
             plugins: None,
@@ -3474,6 +3486,8 @@ mod tests {
             store: None,
             service_tier: None,
             truncation: None,
+            presence_penalty: None,
+            frequency_penalty: None,
             stream: false,
             provider: None,
             plugins: None,

From 9aeb08d52bf1f534184f8abb9c119f0d4fef7233 Mon Sep 17 00:00:00 2001
From: ScriptSmith <ScriptSmith@users.noreply.github.com>
Date: Sun, 29 Mar 2026 17:46:32 +1000
Subject: [PATCH 2/8] Update specs

---
 openapi/hadrian.openapi.json | 20154 ++++++++++++++++++++++-----------
 src/api_types/responses.rs   |     4 +-
 2 files changed, 13683 insertions(+), 6475 deletions(-)

diff --git a/openapi/hadrian.openapi.json b/openapi/hadrian.openapi.json
index f7d4a7ef..7d8cbd27 100644
--- a/openapi/hadrian.openapi.json
+++ b/openapi/hadrian.openapi.json
@@ -2,7 +2,7 @@
   "openapi": "3.1.0",
   "info": {
     "title": "Hadrian Gateway API",
-    "description": "**Hadrian Gateway** is an AI Gateway providing a unified OpenAI-compatible API for routing requests to multiple LLM providers.\n\n## Overview\n\nThe gateway provides two main API surfaces:\n\n- **Public API** (`/api/v1/*`) - OpenAI-compatible endpoints for LLM inference. Use these endpoints to create chat completions, text completions, embeddings, and list available models. Requires API key authentication.\n\n- **Admin API** (`/admin/v1/*`) - RESTful management endpoints for multi-tenant configuration. Manage organizations, projects, users, API keys, dynamic providers, usage tracking, and model pricing.\n\n## Authentication\n\nThe gateway supports multiple authentication methods for API access.\n\n### API Key Authentication\n\nAPI keys are the primary authentication method for programmatic access. Keys are created via the Admin API and scoped to organizations, projects, or users.\n\n**Using the Authorization header (recommended):**\n```\nAuthorization: Bearer gw_live_abc123def456...\n```\n\n**Using the X-API-Key header:**\n```\nX-API-Key: gw_live_abc123def456...\n```\n\nBoth headers are supported. The `Authorization: Bearer` format is recommended for compatibility with OpenAI client libraries.\n\n**Example request:**\n```bash\ncurl https://gateway.example.com/api/v1/chat/completions \\\n  -H \\\"Authorization: Bearer gw_live_abc123def456...\\\" \\\n  -H \\\"Content-Type: application/json\\\" \\\n  -d '{\\\"model\\\": \\\"openai/gpt-4\\\", \\\"messages\\\": [{\\\"role\\\": \\\"user\\\", \\\"content\\\": \\\"Hello\\\"}]}'\n```\n\n### JWT Authentication\n\nWhen JWT authentication is enabled, requests can be authenticated using a JWT token from your identity provider.\n\n```\nAuthorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...\n```\n\nThe gateway validates the JWT against the configured JWKS endpoint and extracts the identity from the token claims.\n\n**Example request:**\n```bash\ncurl https://gateway.example.com/api/v1/chat/completions \\\n  -H \\\"Authorization: Bearer eyJhbGciOiJSUzI1NiIs...\\\" \\\n  -H \\\"Content-Type: application/json\\\" \\\n  -d '{\\\"model\\\": \\\"openai/gpt-4\\\", \\\"messages\\\": [{\\\"role\\\": \\\"user\\\", \\\"content\\\": \\\"Hello\\\"}]}'\n```\n\n### Multi-Auth Mode\n\nWhen configured for multi-auth, the gateway accepts both API keys and JWTs using **format-based detection**:\n\n- **X-API-Key header**: Always validated as an API key\n- **Authorization: Bearer header**: Uses format-based detection:\n  - Tokens starting with the configured API key prefix (default: `gw_`) are validated as API keys\n  - All other tokens are validated as JWTs\n\n**Important:** Providing both `X-API-Key` and `Authorization` headers simultaneously results in a 400 error (ambiguous credentials). Choose one authentication method per request.\n\n**Examples:**\n```bash\n# API key in X-API-Key header\ncurl -H \\\"X-API-Key: gw_live_abc123...\\\" https://gateway.example.com/v1/chat/completions\n\n# API key in Authorization: Bearer header (format-based detection)\ncurl -H \\\"Authorization: Bearer gw_live_abc123...\\\" https://gateway.example.com/v1/chat/completions\n\n# JWT in Authorization: Bearer header\ncurl -H \\\"Authorization: Bearer eyJhbGciOiJSUzI1NiIs...\\\" https://gateway.example.com/v1/chat/completions\n```\n\n### Authentication Errors\n\n| Error Code | HTTP Status | Description | Example Response |\n|------------|-------------|-------------|------------------|\n| `unauthorized` | 401 | No authentication credentials provided | `{\\\"error\\\": {\\\"code\\\": \\\"unauthorized\\\", \\\"message\\\": \\\"Authentication required\\\"}}` |\n| `ambiguous_credentials` | 400 | Both X-API-Key and Authorization headers provided | `{\\\"error\\\": {\\\"code\\\": \\\"ambiguous_credentials\\\", \\\"message\\\": \\\"Ambiguous credentials: provide either X-API-Key or Authorization header, not both\\\"}}` |\n| `invalid_api_key` | 401 | API key is invalid, malformed, or revoked | `{\\\"error\\\": {\\\"code\\\": \\\"invalid_api_key\\\", \\\"message\\\": \\\"Invalid API key\\\"}}` |\n| `not_authenticated` | 401 | JWT validation failed | `{\\\"error\\\": {\\\"code\\\": \\\"not_authenticated\\\", \\\"message\\\": \\\"Token validation failed\\\"}}` |\n| `forbidden` | 403 | Valid credentials but insufficient permissions | `{\\\"error\\\": {\\\"code\\\": \\\"forbidden\\\", \\\"message\\\": \\\"Insufficient permissions\\\"}}` |\n\n### Configuration Examples\n\n**API Key Authentication:**\n```toml\n[auth.gateway]\ntype = \\\"api_key\\\"\nheader_name = \\\"X-API-Key\\\"    # Header to read API key from\nkey_prefix = \\\"gw_\\\"           # Valid key prefix\ncache_ttl_secs = 60           # Cache key lookups for 60 seconds\n```\n\n**JWT Authentication:**\n```toml\n[auth.gateway]\ntype = \\\"jwt\\\"\nissuer = \\\"https://auth.example.com\\\"\naudience = \\\"gateway-api\\\"\njwks_url = \\\"https://auth.example.com/.well-known/jwks.json\\\"\nidentity_claim = \\\"sub\\\"       # JWT claim for user identity\n```\n\n**Multi-Auth (both API key and JWT):**\n```toml\n[auth.gateway]\ntype = \\\"multi\\\"\n\n[auth.gateway.api_key]\nheader_name = \\\"X-API-Key\\\"\nkey_prefix = \\\"gw_\\\"\n\n[auth.gateway.jwt]\nissuer = \\\"https://auth.example.com\\\"\naudience = \\\"gateway-api\\\"\njwks_url = \\\"https://auth.example.com/.well-known/jwks.json\\\"\n```\n\n## Pagination\n\nAll Admin API list endpoints use **cursor-based pagination** for stable, performant navigation.\n\n**Query Parameters:**\n- `limit` (optional): Maximum records per page (default: 100, max: 1000)\n- `cursor` (optional): Opaque cursor from previous response's `next_cursor` or `prev_cursor`\n- `direction` (optional): `forward` (default) or `backward`\n\n**Response:**\n```json\n{\n  \\\"data\\\": [...],\n  \\\"pagination\\\": {\n    \\\"limit\\\": 100,\n    \\\"has_more\\\": true,\n    \\\"next_cursor\\\": \\\"MTczMzU4MDgwMDAwMDphYmMxMjM0...\\\",\n    \\\"prev_cursor\\\": null\n  }\n}\n```\n\n## Model Routing\n\nModels can be addressed in several ways:\n\n- **Static routing**: `provider-name/model-name` routes to config-defined providers\n- **Dynamic routing**: `:org/{ORG}/{PROVIDER}/{MODEL}` routes to database-backed providers\n- **Default**: When no prefix is specified, routes to the default provider\n\n## Error Codes\n\nAll errors follow a consistent JSON format:\n\n```json\n{\n  \\\"error\\\": {\n    \\\"code\\\": \\\"error_code\\\",\n    \\\"message\\\": \\\"Human-readable error message\\\",\n    \\\"details\\\": { ... }  // Optional additional context\n  }\n}\n```\n\n### Authentication & Authorization Errors\n\n| Code | HTTP Status | Description |\n|------|-------------|-------------|\n| `unauthorized` | 401 | Missing or invalid API key/token |\n| `invalid_api_key` | 401 | API key is invalid, expired, or revoked |\n| `forbidden` | 403 | Valid credentials but insufficient permissions |\n| `not_authenticated` | 401 | Authentication required for this operation |\n\n### Rate Limiting & Budget Errors\n\n| Code | HTTP Status | Description |\n|------|-------------|-------------|\n| `rate_limit_exceeded` | 429 | Request rate limit exceeded. Check `Retry-After` header. |\n| `budget_exceeded` | 402 | Budget limit exceeded for the configured period. Details include `limit_cents`, `current_spend_cents`, and `period`. |\n| `cache_required` | 503 | Budget enforcement requires cache to be configured |\n\n### Request Validation Errors\n\n| Code | HTTP Status | Description |\n|------|-------------|-------------|\n| `validation_error` | 400 | Request body validation failed |\n| `bad_request` | 400 | Malformed request |\n| `routing_error` | 400 | Model routing failed (invalid model string or provider not found) |\n| `not_found` | 404 | Requested resource not found |\n| `conflict` | 409 | Resource already exists or conflicts with existing state |\n\n### Provider & Gateway Errors\n\n| Code | HTTP Status | Description |\n|------|-------------|-------------|\n| `provider_error` | 502 | Upstream LLM provider returned an error |\n| `request_failed` | 502 | Failed to communicate with upstream provider |\n| `circuit_breaker_open` | 503 | Provider circuit breaker is open due to repeated failures |\n| `response_read_error` | 500 | Failed to read provider response |\n| `response_builder` | 500 | Failed to build response from provider data |\n| `internal_error` | 500 | Internal server error |\n\n### Guardrails Errors\n\n| Code | HTTP Status | Description |\n|------|-------------|-------------|\n| `guardrails_blocked` | 400 | Content blocked by guardrails policy. Response includes `violations` array. |\n| `guardrails_timeout` | 504 | Guardrails evaluation timed out |\n| `guardrails_provider_error` | 502 | Error communicating with guardrails provider |\n| `guardrails_auth_error` | 502 | Authentication failed with guardrails provider |\n| `guardrails_rate_limited` | 429 | Guardrails provider rate limit exceeded |\n| `guardrails_config_error` | 500 | Invalid guardrails configuration |\n| `guardrails_parse_error` | 400 | Failed to parse content for guardrails evaluation |\n\n### Admin API Errors\n\n| Code | HTTP Status | Description |\n|------|-------------|-------------|\n| `database_required` | 503 | Database not configured (required for admin operations) |\n| `services_required` | 503 | Required services not initialized |\n| `not_configured` | 503 | Required feature or service not configured |\n| `database_error` | 500 | Database operation failed |\n\n## Rate Limiting\n\nThe gateway implements multiple layers of rate limiting to protect against abuse and ensure fair usage.\n\n### Rate Limit Types\n\n| Type | Scope | Default | Description |\n|------|-------|---------|-------------|\n| **Requests per minute** | API Key | 60 | Maximum requests per minute per API key |\n| **Requests per day** | API Key | Unlimited | Optional daily request limit per API key |\n| **Tokens per minute** | API Key | 100,000 | Maximum tokens processed per minute |\n| **Tokens per day** | API Key | Unlimited | Optional daily token limit |\n| **Concurrent requests** | API Key | 10 | Maximum simultaneous in-flight requests |\n| **IP requests per minute** | IP Address | 120 | Rate limit for unauthenticated requests |\n\n### Rate Limit Headers\n\nAll API responses include rate limit information in HTTP headers.\n\n#### Request Rate Limit Headers\n\n| Header | Description | Example |\n|--------|-------------|---------|\n| `X-RateLimit-Limit` | Maximum requests allowed in the current window | `60` |\n| `X-RateLimit-Remaining` | Requests remaining in the current window | `45` |\n| `X-RateLimit-Reset` | Seconds until the rate limit window resets | `42` |\n\n#### Token Rate Limit Headers\n\n| Header | Description | Example |\n|--------|-------------|---------|\n| `X-TokenRateLimit-Limit` | Maximum tokens allowed per minute | `100000` |\n| `X-TokenRateLimit-Remaining` | Tokens remaining in the current minute | `85000` |\n| `X-TokenRateLimit-Used` | Tokens used in the current minute | `15000` |\n| `X-TokenRateLimit-Day-Limit` | Maximum tokens allowed per day (if configured) | `1000000` |\n| `X-TokenRateLimit-Day-Remaining` | Tokens remaining today (if configured) | `950000` |\n\n#### Rate Limit Exceeded Response\n\nWhen a rate limit is exceeded, the API returns HTTP 429 with:\n\n```json\n{\n  \\\"error\\\": {\n    \\\"code\\\": \\\"rate_limit_exceeded\\\",\n    \\\"message\\\": \\\"Rate limit exceeded: 60 requests per minute\\\",\n    \\\"details\\\": {\n      \\\"limit\\\": 60,\n      \\\"window\\\": \\\"minute\\\",\n      \\\"retry_after_secs\\\": 42\n    }\n  }\n}\n```\n\nThe `Retry-After` header indicates seconds to wait before retrying:\n\n```\nHTTP/1.1 429 Too Many Requests\nRetry-After: 42\nX-RateLimit-Limit: 60\nX-RateLimit-Remaining: 0\nX-RateLimit-Reset: 42\n```\n\n### IP-Based Rate Limiting\n\nUnauthenticated requests (requests without a valid API key) are rate limited by IP address. This protects public endpoints like `/health` from abuse.\n\n- **Default:** 120 requests per minute per IP\n- **Client IP Detection:** Respects `X-Forwarded-For` and `X-Real-IP` headers when trusted proxies are configured\n- **Configuration:** Can be disabled or adjusted via `limits.rate_limits.ip_rate_limits` in config\n\n### Rate Limit Configuration\n\nRate limits are configured hierarchically:\n\n1. **Global defaults** (in `gateway.toml`):\n```toml\n[limits.rate_limits]\nrequests_per_minute = 60\ntokens_per_minute = 100000\nconcurrent_requests = 10\n\n[limits.rate_limits.ip_rate_limits]\nenabled = true\nrequests_per_minute = 120\n```\n\n2. **Per-API key** limits can override global defaults (when creating API keys via Admin API)\n\n### Best Practices\n\n- **Implement exponential backoff**: When receiving 429 responses, wait the `Retry-After` duration before retrying\n- **Monitor rate limit headers**: Track `X-RateLimit-Remaining` to proactively throttle requests\n- **Use streaming for long responses**: Streaming responses don't hold connections during generation\n- **Batch requests when possible**: Combine multiple small requests into larger batches\n",
+    "description": "**Hadrian Gateway** is an AI Gateway providing a unified OpenAI-compatible API for routing requests to multiple LLM providers.\n\n## Overview\n\nThe gateway provides two main API surfaces:\n\n- **Public API** (`/api/v1/*`) - OpenAI-compatible endpoints for LLM inference. Use these endpoints to create chat completions, text completions, embeddings, and list available models. Authentication depends on the configured `auth.mode` (API key, IdP, IAP, or none).\n\n- **Admin API** (`/admin/v1/*`) - RESTful management endpoints for multi-tenant configuration. Manage organizations, projects, users, API keys, dynamic providers, usage tracking, and model pricing.\n\n## Authentication\n\nThe gateway supports multiple authentication methods for API access.\n\n### API Key Authentication\n\nAPI keys are the primary authentication method for programmatic access. Keys are created via the Admin API and scoped to organizations, projects, or users.\n\n**Using the Authorization header (recommended):**\n```\nAuthorization: Bearer gw_live_abc123def456...\n```\n\n**Using the X-API-Key header:**\n```\nX-API-Key: gw_live_abc123def456...\n```\n\nBoth headers are supported. The `Authorization: Bearer` format is recommended for compatibility with OpenAI client libraries.\n\n**Example request:**\n```bash\ncurl https://gateway.example.com/api/v1/chat/completions \\\n  -H \\\"Authorization: Bearer gw_live_abc123def456...\\\" \\\n  -H \\\"Content-Type: application/json\\\" \\\n  -d '{\\\"model\\\": \\\"openai/gpt-4\\\", \\\"messages\\\": [{\\\"role\\\": \\\"user\\\", \\\"content\\\": \\\"Hello\\\"}]}'\n```\n\n### JWT Authentication\n\nWhen JWT authentication is enabled, requests can be authenticated using a JWT token from your identity provider.\n\n```\nAuthorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...\n```\n\nThe gateway validates the JWT against the configured JWKS endpoint and extracts the identity from the token claims.\n\n**Example request:**\n```bash\ncurl https://gateway.example.com/api/v1/chat/completions \\\n  -H \\\"Authorization: Bearer eyJhbGciOiJSUzI1NiIs...\\\" \\\n  -H \\\"Content-Type: application/json\\\" \\\n  -d '{\\\"model\\\": \\\"openai/gpt-4\\\", \\\"messages\\\": [{\\\"role\\\": \\\"user\\\", \\\"content\\\": \\\"Hello\\\"}]}'\n```\n\n### Multi-Auth Mode\n\nWhen configured for multi-auth, the gateway accepts both API keys and JWTs using **format-based detection**:\n\n- **X-API-Key header**: Always validated as an API key\n- **Authorization: Bearer header**: Uses format-based detection:\n  - Tokens starting with the configured API key prefix (default: `gw_`) are validated as API keys\n  - All other tokens are validated as JWTs\n\n**Important:** Providing both `X-API-Key` and `Authorization` headers simultaneously results in a 400 error (ambiguous credentials). Choose one authentication method per request.\n\n**Examples:**\n```bash\n# API key in X-API-Key header\ncurl -H \\\"X-API-Key: gw_live_abc123...\\\" https://gateway.example.com/v1/chat/completions\n\n# API key in Authorization: Bearer header (format-based detection)\ncurl -H \\\"Authorization: Bearer gw_live_abc123...\\\" https://gateway.example.com/v1/chat/completions\n\n# JWT in Authorization: Bearer header\ncurl -H \\\"Authorization: Bearer eyJhbGciOiJSUzI1NiIs...\\\" https://gateway.example.com/v1/chat/completions\n```\n\n### Authentication Errors\n\n| Error Code | HTTP Status | Description | Example Response |\n|------------|-------------|-------------|------------------|\n| `unauthorized` | 401 | No authentication credentials provided | `{\\\"error\\\": {\\\"code\\\": \\\"unauthorized\\\", \\\"message\\\": \\\"Authentication required\\\"}}` |\n| `ambiguous_credentials` | 400 | Both X-API-Key and Authorization headers provided | `{\\\"error\\\": {\\\"code\\\": \\\"ambiguous_credentials\\\", \\\"message\\\": \\\"Ambiguous credentials: provide either X-API-Key or Authorization header, not both\\\"}}` |\n| `invalid_api_key` | 401 | API key is invalid, malformed, or revoked | `{\\\"error\\\": {\\\"code\\\": \\\"invalid_api_key\\\", \\\"message\\\": \\\"Invalid API key\\\"}}` |\n| `not_authenticated` | 401 | JWT validation failed | `{\\\"error\\\": {\\\"code\\\": \\\"not_authenticated\\\", \\\"message\\\": \\\"Token validation failed\\\"}}` |\n| `forbidden` | 403 | Valid credentials but insufficient permissions | `{\\\"error\\\": {\\\"code\\\": \\\"forbidden\\\", \\\"message\\\": \\\"Insufficient permissions\\\"}}` |\n\n### Configuration Examples\n\n**API Key Authentication:**\n```toml\n[auth.mode]\ntype = \\\"api_key\\\"\n\n[auth.api_key]\nheader_name = \\\"X-API-Key\\\"    # Header to read API key from\nkey_prefix = \\\"gw_\\\"           # Valid key prefix\ncache_ttl_secs = 60           # Cache key lookups for 60 seconds\n```\n\n**IdP Authentication (SSO + API keys + JWT):**\n```toml\n[auth.mode]\ntype = \\\"idp\\\"\n\n[auth.api_key]\nheader_name = \\\"X-API-Key\\\"\nkey_prefix = \\\"gw_\\\"\n\n[auth.session]\nsecure = true\n```\n\n**Identity-Aware Proxy (IAP):**\n```toml\n[auth.mode]\ntype = \\\"iap\\\"\nidentity_header = \\\"X-Forwarded-User\\\"\nemail_header = \\\"X-Forwarded-Email\\\"\n```\n\n## Pagination\n\nAll Admin API list endpoints use **cursor-based pagination** for stable, performant navigation.\n\n**Query Parameters:**\n- `limit` (optional): Maximum records per page (default: 100, max: 1000)\n- `cursor` (optional): Opaque cursor from previous response's `next_cursor` or `prev_cursor`\n- `direction` (optional): `forward` (default) or `backward`\n\n**Response:**\n```json\n{\n  \\\"data\\\": [...],\n  \\\"pagination\\\": {\n    \\\"limit\\\": 100,\n    \\\"has_more\\\": true,\n    \\\"next_cursor\\\": \\\"MTczMzU4MDgwMDAwMDphYmMxMjM0...\\\",\n    \\\"prev_cursor\\\": null\n  }\n}\n```\n\n## Model Routing\n\nModels can be addressed in several ways:\n\n- **Static routing**: `provider-name/model-name` routes to config-defined providers\n- **Dynamic routing**: `:org/{ORG}/{PROVIDER}/{MODEL}` routes to database-backed providers\n- **Default**: When no prefix is specified, routes to the default provider\n\n## Error Codes\n\nAll errors follow a consistent JSON format:\n\n```json\n{\n  \\\"error\\\": {\n    \\\"code\\\": \\\"error_code\\\",\n    \\\"message\\\": \\\"Human-readable error message\\\",\n    \\\"details\\\": { ... }  // Optional additional context\n  }\n}\n```\n\n### Authentication & Authorization Errors\n\n| Code | HTTP Status | Description |\n|------|-------------|-------------|\n| `unauthorized` | 401 | Missing or invalid API key/token |\n| `invalid_api_key` | 401 | API key is invalid, expired, or revoked |\n| `forbidden` | 403 | Valid credentials but insufficient permissions |\n| `not_authenticated` | 401 | Authentication required for this operation |\n\n### Rate Limiting & Budget Errors\n\n| Code | HTTP Status | Description |\n|------|-------------|-------------|\n| `rate_limit_exceeded` | 429 | Request rate limit exceeded. Check `Retry-After` header. |\n| `budget_exceeded` | 402 | Budget limit exceeded for the configured period. Details include `limit_cents`, `current_spend_cents`, and `period`. |\n| `cache_required` | 503 | Budget enforcement requires cache to be configured |\n\n### Request Validation Errors\n\n| Code | HTTP Status | Description |\n|------|-------------|-------------|\n| `validation_error` | 400 | Request body validation failed |\n| `bad_request` | 400 | Malformed request |\n| `routing_error` | 400 | Model routing failed (invalid model string or provider not found) |\n| `not_found` | 404 | Requested resource not found |\n| `conflict` | 409 | Resource already exists or conflicts with existing state |\n\n### Provider & Gateway Errors\n\n| Code | HTTP Status | Description |\n|------|-------------|-------------|\n| `provider_error` | 502 | Upstream LLM provider returned an error |\n| `request_failed` | 502 | Failed to communicate with upstream provider |\n| `circuit_breaker_open` | 503 | Provider circuit breaker is open due to repeated failures |\n| `response_read_error` | 500 | Failed to read provider response |\n| `response_builder` | 500 | Failed to build response from provider data |\n| `internal_error` | 500 | Internal server error |\n\n### Guardrails Errors\n\n| Code | HTTP Status | Description |\n|------|-------------|-------------|\n| `guardrails_blocked` | 400 | Content blocked by guardrails policy. Response includes `violations` array. |\n| `guardrails_timeout` | 504 | Guardrails evaluation timed out |\n| `guardrails_provider_error` | 502 | Error communicating with guardrails provider |\n| `guardrails_auth_error` | 502 | Authentication failed with guardrails provider |\n| `guardrails_rate_limited` | 429 | Guardrails provider rate limit exceeded |\n| `guardrails_config_error` | 500 | Invalid guardrails configuration |\n| `guardrails_parse_error` | 400 | Failed to parse content for guardrails evaluation |\n\n### Admin API Errors\n\n| Code | HTTP Status | Description |\n|------|-------------|-------------|\n| `database_required` | 503 | Database not configured (required for admin operations) |\n| `services_required` | 503 | Required services not initialized |\n| `not_configured` | 503 | Required feature or service not configured |\n| `database_error` | 500 | Database operation failed |\n\n## Rate Limiting\n\nThe gateway implements multiple layers of rate limiting to protect against abuse and ensure fair usage.\n\n### Rate Limit Types\n\n| Type | Scope | Default | Description |\n|------|-------|---------|-------------|\n| **Requests per minute** | API Key | 60 | Maximum requests per minute per API key |\n| **Requests per day** | API Key | Unlimited | Optional daily request limit per API key |\n| **Tokens per minute** | API Key | 100,000 | Maximum tokens processed per minute |\n| **Tokens per day** | API Key | Unlimited | Optional daily token limit |\n| **Concurrent requests** | API Key | 10 | Maximum simultaneous in-flight requests |\n| **IP requests per minute** | IP Address | 120 | Rate limit for unauthenticated requests |\n\n### Rate Limit Headers\n\nAll API responses include rate limit information in HTTP headers.\n\n#### Request Rate Limit Headers\n\n| Header | Description | Example |\n|--------|-------------|---------|\n| `X-RateLimit-Limit` | Maximum requests allowed in the current window | `60` |\n| `X-RateLimit-Remaining` | Requests remaining in the current window | `45` |\n| `X-RateLimit-Reset` | Seconds until the rate limit window resets | `42` |\n\n#### Token Rate Limit Headers\n\n| Header | Description | Example |\n|--------|-------------|---------|\n| `X-TokenRateLimit-Limit` | Maximum tokens allowed per minute | `100000` |\n| `X-TokenRateLimit-Remaining` | Tokens remaining in the current minute | `85000` |\n| `X-TokenRateLimit-Used` | Tokens used in the current minute | `15000` |\n| `X-TokenRateLimit-Day-Limit` | Maximum tokens allowed per day (if configured) | `1000000` |\n| `X-TokenRateLimit-Day-Remaining` | Tokens remaining today (if configured) | `950000` |\n\n#### Rate Limit Exceeded Response\n\nWhen a rate limit is exceeded, the API returns HTTP 429 with:\n\n```json\n{\n  \\\"error\\\": {\n    \\\"code\\\": \\\"rate_limit_exceeded\\\",\n    \\\"message\\\": \\\"Rate limit exceeded: 60 requests per minute\\\",\n    \\\"details\\\": {\n      \\\"limit\\\": 60,\n      \\\"window\\\": \\\"minute\\\",\n      \\\"retry_after_secs\\\": 42\n    }\n  }\n}\n```\n\nThe `Retry-After` header indicates seconds to wait before retrying:\n\n```\nHTTP/1.1 429 Too Many Requests\nRetry-After: 42\nX-RateLimit-Limit: 60\nX-RateLimit-Remaining: 0\nX-RateLimit-Reset: 42\n```\n\n### IP-Based Rate Limiting\n\nUnauthenticated requests (requests without a valid API key) are rate limited by IP address. This protects public endpoints like `/health` from abuse.\n\n- **Default:** 120 requests per minute per IP\n- **Client IP Detection:** Respects `X-Forwarded-For` and `X-Real-IP` headers when trusted proxies are configured\n- **Configuration:** Can be disabled or adjusted via `limits.rate_limits.ip_rate_limits` in config\n\n### Rate Limit Configuration\n\nRate limits are configured hierarchically:\n\n1. **Global defaults** (in `hadrian.toml`):\n```toml\n[limits.rate_limits]\nrequests_per_minute = 60\ntokens_per_minute = 100000\nconcurrent_requests = 10\n\n[limits.rate_limits.ip_rate_limits]\nenabled = true\nrequests_per_minute = 120\n```\n\n2. **Per-API key** limits can override global defaults (when creating API keys via Admin API)\n\n### Best Practices\n\n- **Implement exponential backoff**: When receiving 429 responses, wait the `Retry-After` duration before retrying\n- **Monitor rate limit headers**: Track `X-RateLimit-Remaining` to proactively throttle requests\n- **Use streaming for long responses**: Streaming responses don't hold connections during generation\n- **Batch requests when possible**: Combine multiple small requests into larger batches\n",
     "license": {
       "name": "Apache-2.0 OR MIT",
       "url": "https://github.com/ScriptSmith/hadrian/blob/main/LICENSE-APACHE"
@@ -587,13 +587,13 @@
         }
       }
     },
-    "/admin/v1/api-keys/{key_id}/usage/by-model": {
+    "/admin/v1/api-keys/{key_id}/usage/by-date-model": {
       "get": {
         "tags": [
           "usage"
         ],
-        "summary": "Get usage by model for an API key",
-        "operationId": "usage_get_by_model",
+        "summary": "Get usage by date and model for an API key",
+        "operationId": "usage_get_by_date_model",
         "parameters": [
           {
             "name": "key_id",
@@ -632,38 +632,28 @@
         ],
         "responses": {
           "200": {
-            "description": "Usage breakdown by model",
+            "description": "Daily usage breakdown by model",
             "content": {
               "application/json": {
                 "schema": {
                   "type": "array",
                   "items": {
-                    "$ref": "#/components/schemas/ModelSpendResponse"
+                    "$ref": "#/components/schemas/DailyModelSpendResponse"
                   }
                 }
               }
             }
-          },
-          "404": {
-            "description": "API key not found",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
-            }
           }
         }
       }
     },
-    "/admin/v1/api-keys/{key_id}/usage/by-referer": {
+    "/admin/v1/api-keys/{key_id}/usage/by-date-pricing-source": {
       "get": {
         "tags": [
           "usage"
         ],
-        "summary": "Get usage by referer for an API key",
-        "operationId": "usage_get_by_referer",
+        "summary": "Get usage by date and pricing source for an API key",
+        "operationId": "usage_get_by_date_pricing_source",
         "parameters": [
           {
             "name": "key_id",
@@ -702,39 +692,28 @@
         ],
         "responses": {
           "200": {
-            "description": "Usage breakdown by HTTP referer",
+            "description": "Daily usage breakdown by pricing source",
             "content": {
               "application/json": {
                 "schema": {
                   "type": "array",
                   "items": {
-                    "$ref": "#/components/schemas/RefererSpendResponse"
+                    "$ref": "#/components/schemas/DailyPricingSourceSpendResponse"
                   }
                 }
               }
             }
-          },
-          "404": {
-            "description": "API key not found",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
-            }
           }
         }
       }
     },
-    "/admin/v1/api-keys/{key_id}/usage/forecast": {
+    "/admin/v1/api-keys/{key_id}/usage/by-date-provider": {
       "get": {
         "tags": [
           "usage"
         ],
-        "summary": "Get cost forecast for an API key",
-        "description": "Uses historical usage data to predict when the budget will be exhausted.\nReturns average daily spend, projected exhaustion date, and confidence intervals.",
-        "operationId": "usage_get_forecast",
+        "summary": "Get usage by date and provider for an API key",
+        "operationId": "usage_get_by_date_provider",
         "parameters": [
           {
             "name": "key_id",
@@ -747,49 +726,40 @@
             }
           },
           {
-            "name": "lookback_days",
+            "name": "start_date",
             "in": "query",
-            "description": "Number of days of historical data to use (default: 30)",
+            "description": "Start date (YYYY-MM-DD)",
             "required": false,
             "schema": {
               "type": [
-                "integer",
+                "string",
                 "null"
-              ],
-              "format": "int32"
+              ]
             }
           },
           {
-            "name": "forecast_days",
+            "name": "end_date",
             "in": "query",
-            "description": "Number of days to forecast ahead (default: 7)",
+            "description": "End date (YYYY-MM-DD)",
             "required": false,
             "schema": {
               "type": [
-                "integer",
+                "string",
                 "null"
-              ],
-              "minimum": 0
+              ]
             }
           }
         ],
         "responses": {
           "200": {
-            "description": "Cost forecast",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/CostForecastResponse"
-                }
-              }
-            }
-          },
-          "404": {
-            "description": "API key not found",
+            "description": "Daily usage breakdown by provider",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/DailyProviderSpendResponse"
+                  }
                 }
               }
             }
@@ -797,47 +767,28 @@
         }
       }
     },
-    "/admin/v1/audit-logs": {
+    "/admin/v1/api-keys/{key_id}/usage/by-model": {
       "get": {
         "tags": [
-          "audit-logs"
+          "usage"
         ],
-        "summary": "List audit logs",
-        "operationId": "audit_log_list",
+        "summary": "Get usage by model for an API key",
+        "operationId": "usage_get_by_model",
         "parameters": [
           {
-            "name": "actor_type",
-            "in": "query",
-            "description": "Filter by actor type",
-            "required": false,
-            "schema": {
-              "oneOf": [
-                {
-                  "type": "null"
-                },
-                {
-                  "$ref": "#/components/schemas/AuditActorType"
-                }
-              ]
-            }
-          },
-          {
-            "name": "actor_id",
-            "in": "query",
-            "description": "Filter by actor ID",
-            "required": false,
+            "name": "key_id",
+            "in": "path",
+            "description": "API key ID",
+            "required": true,
             "schema": {
-              "type": [
-                "string",
-                "null"
-              ],
+              "type": "string",
               "format": "uuid"
             }
           },
           {
-            "name": "action",
+            "name": "start_date",
             "in": "query",
-            "description": "Filter by action (e.g., \"api_key.create\")",
+            "description": "Start date (YYYY-MM-DD)",
             "required": false,
             "schema": {
               "type": [
@@ -847,9 +798,9 @@
             }
           },
           {
-            "name": "resource_type",
+            "name": "end_date",
             "in": "query",
-            "description": "Filter by resource type (e.g., \"api_key\")",
+            "description": "End date (YYYY-MM-DD)",
             "required": false,
             "schema": {
               "type": [
@@ -857,89 +808,117 @@
                 "null"
               ]
             }
-          },
-          {
-            "name": "resource_id",
-            "in": "query",
-            "description": "Filter by resource ID",
-            "required": false,
-            "schema": {
-              "type": [
-                "string",
-                "null"
-              ],
-              "format": "uuid"
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Usage breakdown by model",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/ModelSpendResponse"
+                  }
+                }
+              }
             }
           },
-          {
-            "name": "org_id",
-            "in": "query",
-            "description": "Filter by organization ID",
-            "required": false,
-            "schema": {
-              "type": [
-                "string",
-                "null"
-              ],
-              "format": "uuid"
+          "404": {
+            "description": "API key not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
             }
-          },
+          }
+        }
+      }
+    },
+    "/admin/v1/api-keys/{key_id}/usage/by-pricing-source": {
+      "get": {
+        "tags": [
+          "usage"
+        ],
+        "summary": "Get usage by pricing source for an API key",
+        "operationId": "usage_get_by_pricing_source",
+        "parameters": [
           {
-            "name": "project_id",
-            "in": "query",
-            "description": "Filter by project ID",
-            "required": false,
+            "name": "key_id",
+            "in": "path",
+            "description": "API key ID",
+            "required": true,
             "schema": {
-              "type": [
-                "string",
-                "null"
-              ],
+              "type": "string",
               "format": "uuid"
             }
           },
           {
-            "name": "from",
+            "name": "start_date",
             "in": "query",
-            "description": "Start of time range (inclusive)",
+            "description": "Start date (YYYY-MM-DD)",
             "required": false,
             "schema": {
               "type": [
                 "string",
                 "null"
-              ],
-              "format": "date-time"
+              ]
             }
           },
           {
-            "name": "to",
+            "name": "end_date",
             "in": "query",
-            "description": "End of time range (exclusive)",
+            "description": "End date (YYYY-MM-DD)",
             "required": false,
             "schema": {
               "type": [
                 "string",
                 "null"
-              ],
-              "format": "date-time"
+              ]
             }
-          },
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Usage breakdown by pricing source",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/PricingSourceSpendResponse"
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/api-keys/{key_id}/usage/by-provider": {
+      "get": {
+        "tags": [
+          "usage"
+        ],
+        "summary": "Get usage by provider for an API key",
+        "operationId": "usage_get_by_provider",
+        "parameters": [
           {
-            "name": "limit",
-            "in": "query",
-            "description": "Maximum number of results to return",
-            "required": false,
+            "name": "key_id",
+            "in": "path",
+            "description": "API key ID",
+            "required": true,
             "schema": {
-              "type": [
-                "integer",
-                "null"
-              ],
-              "format": "int64"
+              "type": "string",
+              "format": "uuid"
             }
           },
           {
-            "name": "cursor",
+            "name": "start_date",
             "in": "query",
-            "description": "Cursor for pagination (cursor-based pagination)",
+            "description": "Start date (YYYY-MM-DD)",
             "required": false,
             "schema": {
               "type": [
@@ -949,9 +928,9 @@
             }
           },
           {
-            "name": "direction",
+            "name": "end_date",
             "in": "query",
-            "description": "Pagination direction (forward or backward). Only used with cursor.",
+            "description": "End date (YYYY-MM-DD)",
             "required": false,
             "schema": {
               "type": [
@@ -963,17 +942,20 @@
         ],
         "responses": {
           "200": {
-            "description": "List of audit log entries",
+            "description": "Usage breakdown by provider",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/AuditLogListResponse"
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/ProviderSpendResponse"
+                  }
                 }
               }
             }
           },
-          "400": {
-            "description": "Invalid cursor or direction",
+          "404": {
+            "description": "API key not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -985,79 +967,65 @@
         }
       }
     },
-    "/admin/v1/audit-logs/{id}": {
+    "/admin/v1/api-keys/{key_id}/usage/by-referer": {
       "get": {
         "tags": [
-          "audit-logs"
+          "usage"
         ],
-        "summary": "Get an audit log entry by ID",
-        "operationId": "audit_log_get",
+        "summary": "Get usage by referer for an API key",
+        "operationId": "usage_get_by_referer",
         "parameters": [
           {
-            "name": "id",
+            "name": "key_id",
             "in": "path",
-            "description": "Audit log entry ID",
+            "description": "API key ID",
             "required": true,
             "schema": {
               "type": "string",
               "format": "uuid"
             }
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "Audit log entry found",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/AuditLog"
-                }
-              }
+          },
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
             }
           },
-          "404": {
-            "description": "Audit log entry not found",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
             }
           }
-        }
-      }
-    },
-    "/admin/v1/conversations": {
-      "post": {
-        "tags": [
-          "conversations"
         ],
-        "summary": "Create a new conversation",
-        "operationId": "conversation_create",
-        "requestBody": {
-          "content": {
-            "application/json": {
-              "schema": {
-                "$ref": "#/components/schemas/CreateConversation"
-              }
-            }
-          },
-          "required": true
-        },
         "responses": {
-          "201": {
-            "description": "Conversation created",
+          "200": {
+            "description": "Usage breakdown by HTTP referer",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/Conversation"
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/RefererSpendResponse"
+                  }
                 }
               }
             }
           },
           "404": {
-            "description": "Owner not found",
+            "description": "API key not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -1069,124 +1037,65 @@
         }
       }
     },
-    "/admin/v1/conversations/{id}": {
+    "/admin/v1/api-keys/{key_id}/usage/forecast": {
       "get": {
         "tags": [
-          "conversations"
+          "usage"
         ],
-        "summary": "Get a conversation by ID",
-        "operationId": "conversation_get",
+        "summary": "Get cost forecast for an API key",
+        "description": "Uses historical usage data to predict when the budget will be exhausted.\nReturns average daily spend, projected exhaustion date, and confidence intervals.",
+        "operationId": "usage_get_forecast",
         "parameters": [
           {
-            "name": "id",
+            "name": "key_id",
             "in": "path",
-            "description": "Conversation ID",
+            "description": "API key ID",
             "required": true,
             "schema": {
               "type": "string",
               "format": "uuid"
             }
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "Conversation found",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/Conversation"
-                }
-              }
-            }
           },
-          "404": {
-            "description": "Conversation not found",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
-            }
-          }
-        }
-      },
-      "delete": {
-        "tags": [
-          "conversations"
-        ],
-        "summary": "Delete a conversation",
-        "operationId": "conversation_delete",
-        "parameters": [
           {
-            "name": "id",
-            "in": "path",
-            "description": "Conversation ID",
-            "required": true,
+            "name": "lookback_days",
+            "in": "query",
+            "description": "Number of days of historical data to use (default: 30)",
+            "required": false,
             "schema": {
-              "type": "string",
-              "format": "uuid"
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "int32"
             }
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "Conversation deleted"
           },
-          "404": {
-            "description": "Conversation not found",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
-            }
-          }
-        }
-      },
-      "patch": {
-        "tags": [
-          "conversations"
-        ],
-        "summary": "Update a conversation",
-        "description": "Can also be used to move a conversation to a different project or user by providing the `owner` field.",
-        "operationId": "conversation_update",
-        "parameters": [
           {
-            "name": "id",
-            "in": "path",
-            "description": "Conversation ID",
-            "required": true,
+            "name": "forecast_days",
+            "in": "query",
+            "description": "Number of days to forecast ahead (default: 7)",
+            "required": false,
             "schema": {
-              "type": "string",
-              "format": "uuid"
+              "type": [
+                "integer",
+                "null"
+              ],
+              "minimum": 0
             }
           }
         ],
-        "requestBody": {
-          "content": {
-            "application/json": {
-              "schema": {
-                "$ref": "#/components/schemas/UpdateConversation"
-              }
-            }
-          },
-          "required": true
-        },
         "responses": {
           "200": {
-            "description": "Conversation updated",
+            "description": "Cost forecast",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/Conversation"
+                  "$ref": "#/components/schemas/CostForecastResponse"
                 }
               }
             }
           },
           "404": {
-            "description": "Conversation or new owner not found",
+            "description": "API key not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -1198,166 +1107,149 @@
         }
       }
     },
-    "/admin/v1/conversations/{id}/messages": {
-      "post": {
+    "/admin/v1/audit-logs": {
+      "get": {
         "tags": [
-          "conversations"
+          "audit-logs"
         ],
-        "summary": "Append messages to a conversation",
-        "operationId": "conversation_append_messages",
+        "summary": "List audit logs",
+        "operationId": "audit_log_list",
         "parameters": [
           {
-            "name": "id",
-            "in": "path",
-            "description": "Conversation ID",
-            "required": true,
+            "name": "actor_type",
+            "in": "query",
+            "description": "Filter by actor type",
+            "required": false,
             "schema": {
-              "type": "string",
-              "format": "uuid"
-            }
-          }
-        ],
-        "requestBody": {
-          "content": {
-            "application/json": {
-              "schema": {
-                "$ref": "#/components/schemas/AppendMessages"
-              }
+              "oneOf": [
+                {
+                  "type": "null"
+                },
+                {
+                  "$ref": "#/components/schemas/AuditActorType"
+                }
+              ]
             }
           },
-          "required": true
-        },
-        "responses": {
-          "200": {
-            "description": "Messages appended, returns all messages",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "type": "array",
-                  "items": {
-                    "$ref": "#/components/schemas/Message"
-                  }
-                }
-              }
+          {
+            "name": "actor_id",
+            "in": "query",
+            "description": "Filter by actor ID",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ],
+              "format": "uuid"
             }
           },
-          "404": {
-            "description": "Conversation not found",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
+          {
+            "name": "action",
+            "in": "query",
+            "description": "Filter by action (e.g., \"api_key.create\")",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
             }
-          }
-        }
-      }
-    },
-    "/admin/v1/conversations/{id}/pin": {
-      "put": {
-        "tags": [
-          "conversations"
-        ],
-        "summary": "Set pin order for a conversation",
-        "description": "Set `pin_order` to a number to pin the conversation (0 = first, higher = lower in list).\nSet `pin_order` to null to unpin the conversation.",
-        "operationId": "conversation_set_pin",
-        "parameters": [
+          },
           {
-            "name": "id",
-            "in": "path",
-            "description": "Conversation ID",
-            "required": true,
+            "name": "resource_type",
+            "in": "query",
+            "description": "Filter by resource type (e.g., \"api_key\")",
+            "required": false,
             "schema": {
-              "type": "string",
-              "format": "uuid"
+              "type": [
+                "string",
+                "null"
+              ]
             }
-          }
-        ],
-        "requestBody": {
-          "content": {
-            "application/json": {
-              "schema": {
-                "$ref": "#/components/schemas/SetPinOrder"
-              }
+          },
+          {
+            "name": "resource_id",
+            "in": "query",
+            "description": "Filter by resource ID",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ],
+              "format": "uuid"
             }
           },
-          "required": true
-        },
-        "responses": {
-          "200": {
-            "description": "Pin order updated",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/Conversation"
-                }
-              }
+          {
+            "name": "org_id",
+            "in": "query",
+            "description": "Filter by organization ID",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ],
+              "format": "uuid"
             }
           },
-          "404": {
-            "description": "Conversation not found",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
+          {
+            "name": "project_id",
+            "in": "query",
+            "description": "Filter by project ID",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ],
+              "format": "uuid"
             }
-          }
-        }
-      }
-    },
-    "/admin/v1/dlq": {
-      "get": {
-        "tags": [
-          "dlq"
-        ],
-        "summary": "List DLQ entries.",
-        "operationId": "dlq_list",
-        "parameters": [
+          },
           {
-            "name": "entry_type",
+            "name": "from",
             "in": "query",
-            "description": "Filter by entry type (e.g., \"usage_log\").",
+            "description": "Start of time range (inclusive)",
             "required": false,
             "schema": {
               "type": [
                 "string",
                 "null"
-              ]
+              ],
+              "format": "date-time"
             }
           },
           {
-            "name": "limit",
+            "name": "to",
             "in": "query",
-            "description": "Maximum number of entries to return (default: 100).",
+            "description": "End of time range (exclusive)",
             "required": false,
             "schema": {
               "type": [
-                "integer",
+                "string",
                 "null"
               ],
-              "format": "int64"
+              "format": "date-time"
             }
           },
           {
-            "name": "max_retries",
+            "name": "limit",
             "in": "query",
-            "description": "Only return entries with fewer than this many retries.",
+            "description": "Maximum number of results to return",
             "required": false,
             "schema": {
               "type": [
                 "integer",
                 "null"
               ],
-              "format": "int32"
+              "format": "int64"
             }
           },
           {
             "name": "cursor",
             "in": "query",
-            "description": "Cursor for keyset pagination. Encoded as base64 string.",
+            "description": "Cursor for pagination (cursor-based pagination)",
             "required": false,
             "schema": {
               "type": [
@@ -1369,7 +1261,7 @@
           {
             "name": "direction",
             "in": "query",
-            "description": "Pagination direction: \"forward\" (default) or \"backward\".",
+            "description": "Pagination direction (forward or backward). Only used with cursor.",
             "required": false,
             "schema": {
               "type": [
@@ -1381,44 +1273,17 @@
         ],
         "responses": {
           "200": {
-            "description": "List of DLQ entries",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/DlqListResponse"
-                }
-              }
-            }
-          },
-          "400": {
-            "description": "DLQ not configured or invalid cursor",
+            "description": "List of audit log entries",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "$ref": "#/components/schemas/AuditLogListResponse"
                 }
               }
             }
-          }
-        }
-      },
-      "delete": {
-        "tags": [
-          "dlq"
-        ],
-        "summary": "Purge all DLQ entries.",
-        "operationId": "dlq_purge",
-        "responses": {
-          "200": {
-            "description": "Purge result",
-            "content": {
-              "application/json": {
-                "schema": {}
-              }
-            }
           },
           "400": {
-            "description": "DLQ not configured",
+            "description": "Invalid cursor or direction",
             "content": {
               "application/json": {
                 "schema": {
@@ -1430,39 +1295,38 @@
         }
       }
     },
-    "/admin/v1/dlq/prune": {
-      "post": {
+    "/admin/v1/audit-logs/{id}": {
+      "get": {
         "tags": [
-          "dlq"
+          "audit-logs"
         ],
-        "operationId": "dlq_prune",
+        "summary": "Get an audit log entry by ID",
+        "operationId": "audit_log_get",
         "parameters": [
           {
-            "name": "older_than_secs",
-            "in": "query",
-            "description": "Prune entries older than this many seconds (default: TTL from config).",
-            "required": false,
+            "name": "id",
+            "in": "path",
+            "description": "Audit log entry ID",
+            "required": true,
             "schema": {
-              "type": [
-                "integer",
-                "null"
-              ],
-              "format": "int64",
-              "minimum": 0
+              "type": "string",
+              "format": "uuid"
             }
           }
         ],
         "responses": {
           "200": {
-            "description": "Prune result",
+            "description": "Audit log entry found",
             "content": {
               "application/json": {
-                "schema": {}
+                "schema": {
+                  "$ref": "#/components/schemas/AuditLog"
+                }
               }
             }
           },
-          "400": {
-            "description": "DLQ not configured",
+          "404": {
+            "description": "Audit log entry not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -1474,26 +1338,36 @@
         }
       }
     },
-    "/admin/v1/dlq/stats": {
-      "get": {
+    "/admin/v1/conversations": {
+      "post": {
         "tags": [
-          "dlq"
+          "conversations"
         ],
-        "summary": "Get DLQ statistics.",
-        "operationId": "dlq_stats",
+        "summary": "Create a new conversation",
+        "operationId": "conversation_create",
+        "requestBody": {
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/CreateConversation"
+              }
+            }
+          },
+          "required": true
+        },
         "responses": {
-          "200": {
-            "description": "DLQ statistics",
+          "201": {
+            "description": "Conversation created",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/DlqStatsResponse"
+                  "$ref": "#/components/schemas/Conversation"
                 }
               }
             }
           },
-          "400": {
-            "description": "DLQ not configured",
+          "404": {
+            "description": "Owner not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -1505,18 +1379,18 @@
         }
       }
     },
-    "/admin/v1/dlq/{id}": {
+    "/admin/v1/conversations/{id}": {
       "get": {
         "tags": [
-          "dlq"
+          "conversations"
         ],
-        "summary": "Get a specific DLQ entry by ID.",
-        "operationId": "dlq_get",
+        "summary": "Get a conversation by ID",
+        "operationId": "conversation_get",
         "parameters": [
           {
             "name": "id",
             "in": "path",
-            "description": "DLQ entry ID",
+            "description": "Conversation ID",
             "required": true,
             "schema": {
               "type": "string",
@@ -1526,27 +1400,17 @@
         ],
         "responses": {
           "200": {
-            "description": "DLQ entry",
+            "description": "Conversation found",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/DlqEntryResponse"
-                }
-              }
-            }
-          },
-          "400": {
-            "description": "DLQ not configured",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "$ref": "#/components/schemas/Conversation"
                 }
               }
             }
           },
           "404": {
-            "description": "Entry not found",
+            "description": "Conversation not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -1559,15 +1423,15 @@
       },
       "delete": {
         "tags": [
-          "dlq"
+          "conversations"
         ],
-        "summary": "Delete a DLQ entry.",
-        "operationId": "dlq_delete",
+        "summary": "Delete a conversation",
+        "operationId": "conversation_delete",
         "parameters": [
           {
             "name": "id",
             "in": "path",
-            "description": "DLQ entry ID",
+            "description": "Conversation ID",
             "required": true,
             "schema": {
               "type": "string",
@@ -1577,20 +1441,10 @@
         ],
         "responses": {
           "200": {
-            "description": "Entry deleted"
-          },
-          "400": {
-            "description": "DLQ not configured",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
-            }
+            "description": "Conversation deleted"
           },
           "404": {
-            "description": "Entry not found",
+            "description": "Conversation not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -1600,20 +1454,19 @@
             }
           }
         }
-      }
-    },
-    "/admin/v1/dlq/{id}/retry": {
-      "post": {
+      },
+      "patch": {
         "tags": [
-          "dlq"
+          "conversations"
         ],
-        "summary": "Retry a specific DLQ entry.",
-        "operationId": "dlq_retry",
+        "summary": "Update a conversation",
+        "description": "Can also be used to move a conversation to a different project or user by providing the `owner` field.",
+        "operationId": "conversation_update",
         "parameters": [
           {
             "name": "id",
             "in": "path",
-            "description": "DLQ entry ID",
+            "description": "Conversation ID",
             "required": true,
             "schema": {
               "type": "string",
@@ -1621,29 +1474,29 @@
             }
           }
         ],
-        "responses": {
-          "200": {
-            "description": "Retry result",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/DlqRetryResponse"
-                }
+        "requestBody": {
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/UpdateConversation"
               }
             }
           },
-          "400": {
-            "description": "DLQ not configured or invalid entry",
+          "required": true
+        },
+        "responses": {
+          "200": {
+            "description": "Conversation updated",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "$ref": "#/components/schemas/Conversation"
                 }
               }
             }
           },
           "404": {
-            "description": "Entry not found",
+            "description": "Conversation or new owner not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -1655,36 +1508,51 @@
         }
       }
     },
-    "/admin/v1/dynamic-providers": {
+    "/admin/v1/conversations/{id}/messages": {
       "post": {
         "tags": [
-          "dynamic-providers"
+          "conversations"
+        ],
+        "summary": "Append messages to a conversation",
+        "operationId": "conversation_append_messages",
+        "parameters": [
+          {
+            "name": "id",
+            "in": "path",
+            "description": "Conversation ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          }
         ],
-        "summary": "Create a dynamic provider",
-        "operationId": "dynamic_provider_create",
         "requestBody": {
           "content": {
             "application/json": {
               "schema": {
-                "$ref": "#/components/schemas/CreateDynamicProvider"
+                "$ref": "#/components/schemas/AppendMessages"
               }
             }
           },
           "required": true
         },
         "responses": {
-          "201": {
-            "description": "Dynamic provider created",
+          "200": {
+            "description": "Messages appended, returns all messages",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/DynamicProvider"
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/Message"
+                  }
                 }
               }
             }
           },
           "404": {
-            "description": "Owner not found",
+            "description": "Conversation not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -1696,18 +1564,19 @@
         }
       }
     },
-    "/admin/v1/dynamic-providers/{id}": {
-      "get": {
+    "/admin/v1/conversations/{id}/pin": {
+      "put": {
         "tags": [
-          "dynamic-providers"
+          "conversations"
         ],
-        "summary": "Get a dynamic provider by ID",
-        "operationId": "dynamic_provider_get",
+        "summary": "Set pin order for a conversation",
+        "description": "Set `pin_order` to a number to pin the conversation (0 = first, higher = lower in list).\nSet `pin_order` to null to unpin the conversation.",
+        "operationId": "conversation_set_pin",
         "parameters": [
           {
             "name": "id",
             "in": "path",
-            "description": "Dynamic provider ID",
+            "description": "Conversation ID",
             "required": true,
             "schema": {
               "type": "string",
@@ -1715,19 +1584,29 @@
             }
           }
         ],
+        "requestBody": {
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/SetPinOrder"
+              }
+            }
+          },
+          "required": true
+        },
         "responses": {
           "200": {
-            "description": "Dynamic provider found",
+            "description": "Pin order updated",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/DynamicProvider"
+                  "$ref": "#/components/schemas/Conversation"
                 }
               }
             }
           },
           "404": {
-            "description": "Dynamic provider not found",
+            "description": "Conversation not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -1737,82 +1616,92 @@
             }
           }
         }
-      },
-      "delete": {
+      }
+    },
+    "/admin/v1/dlq": {
+      "get": {
         "tags": [
-          "dynamic-providers"
+          "dlq"
         ],
-        "summary": "Delete a dynamic provider",
-        "operationId": "dynamic_provider_delete",
+        "summary": "List DLQ entries.",
+        "operationId": "dlq_list",
         "parameters": [
           {
-            "name": "id",
-            "in": "path",
-            "description": "Dynamic provider ID",
-            "required": true,
+            "name": "entry_type",
+            "in": "query",
+            "description": "Filter by entry type (e.g., \"usage_log\").",
+            "required": false,
             "schema": {
-              "type": "string",
-              "format": "uuid"
+              "type": [
+                "string",
+                "null"
+              ]
             }
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "Dynamic provider deleted"
           },
-          "404": {
-            "description": "Dynamic provider not found",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
+          {
+            "name": "limit",
+            "in": "query",
+            "description": "Maximum number of entries to return (default: 100).",
+            "required": false,
+            "schema": {
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "int64"
             }
-          }
-        }
-      },
-      "patch": {
-        "tags": [
-          "dynamic-providers"
-        ],
-        "summary": "Update a dynamic provider",
-        "operationId": "dynamic_provider_update",
-        "parameters": [
+          },
           {
-            "name": "id",
-            "in": "path",
-            "description": "Dynamic provider ID",
-            "required": true,
+            "name": "max_retries",
+            "in": "query",
+            "description": "Only return entries with fewer than this many retries.",
+            "required": false,
             "schema": {
-              "type": "string",
-              "format": "uuid"
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "int32"
             }
-          }
-        ],
-        "requestBody": {
-          "content": {
-            "application/json": {
-              "schema": {
-                "$ref": "#/components/schemas/UpdateDynamicProvider"
-              }
+          },
+          {
+            "name": "cursor",
+            "in": "query",
+            "description": "Cursor for keyset pagination. Encoded as base64 string.",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
             }
           },
-          "required": true
-        },
+          {
+            "name": "direction",
+            "in": "query",
+            "description": "Pagination direction: \"forward\" (default) or \"backward\".",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        ],
         "responses": {
           "200": {
-            "description": "Dynamic provider updated",
+            "description": "List of DLQ entries",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/DynamicProvider"
+                  "$ref": "#/components/schemas/DlqListResponse"
                 }
               }
             }
           },
-          "404": {
-            "description": "Dynamic provider not found",
+          "400": {
+            "description": "DLQ not configured or invalid cursor",
             "content": {
               "application/json": {
                 "schema": {
@@ -1822,29 +1711,68 @@
             }
           }
         }
-      }
-    },
-    "/admin/v1/me": {
+      },
       "delete": {
         "tags": [
-          "me"
+          "dlq"
         ],
-        "summary": "Delete current user and all associated data (GDPR Article 17 - Right to Erasure)",
-        "description": "Permanently deletes the authenticated user and all associated data including:\n- User record\n- Organization and project memberships\n- API keys owned by the user\n- Conversations owned by the user\n- Dynamic providers owned by the user\n- Usage records for user's API keys\n\nThis endpoint allows users to delete their own account without admin permissions.\nThe user is identified from the authenticated session.\n\n**Warning:** This operation is irreversible.",
-        "operationId": "me_delete",
+        "summary": "Purge all DLQ entries.",
+        "operationId": "dlq_purge",
         "responses": {
           "200": {
-            "description": "User deleted",
+            "description": "Purge result",
+            "content": {
+              "application/json": {
+                "schema": {}
+              }
+            }
+          },
+          "400": {
+            "description": "DLQ not configured",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/UserDeletionResponse"
+                  "$ref": "#/components/schemas/ErrorResponse"
                 }
               }
             }
+          }
+        }
+      }
+    },
+    "/admin/v1/dlq/prune": {
+      "post": {
+        "tags": [
+          "dlq"
+        ],
+        "operationId": "dlq_prune",
+        "parameters": [
+          {
+            "name": "older_than_secs",
+            "in": "query",
+            "description": "Prune entries older than this many seconds (default: TTL from config).",
+            "required": false,
+            "schema": {
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "int64",
+              "minimum": 0
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Prune result",
+            "content": {
+              "application/json": {
+                "schema": {}
+              }
+            }
           },
-          "401": {
-            "description": "User not identified from session",
+          "400": {
+            "description": "DLQ not configured",
             "content": {
               "application/json": {
                 "schema": {
@@ -1852,9 +1780,30 @@
                 }
               }
             }
+          }
+        }
+      }
+    },
+    "/admin/v1/dlq/stats": {
+      "get": {
+        "tags": [
+          "dlq"
+        ],
+        "summary": "Get DLQ statistics.",
+        "operationId": "dlq_stats",
+        "responses": {
+          "200": {
+            "description": "DLQ statistics",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/DlqStatsResponse"
+                }
+              }
+            }
           },
-          "404": {
-            "description": "User not found",
+          "400": {
+            "description": "DLQ not configured",
             "content": {
               "application/json": {
                 "schema": {
@@ -1866,27 +1815,38 @@
         }
       }
     },
-    "/admin/v1/me/export": {
+    "/admin/v1/dlq/{id}": {
       "get": {
         "tags": [
-          "me"
+          "dlq"
+        ],
+        "summary": "Get a specific DLQ entry by ID.",
+        "operationId": "dlq_get",
+        "parameters": [
+          {
+            "name": "id",
+            "in": "path",
+            "description": "DLQ entry ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          }
         ],
-        "summary": "Export current user's data (GDPR Article 15 - Right of Access)",
-        "description": "Exports all personal data associated with the authenticated user including:\n- User profile\n- Organization and project memberships\n- API keys (excluding sensitive hash)\n- Conversations\n- Usage summary\n- Audit logs where user was the actor\n\nThis endpoint allows users to export their own data without admin permissions.\nThe user is identified from the authenticated session.",
-        "operationId": "me_export",
         "responses": {
           "200": {
-            "description": "User data export",
+            "description": "DLQ entry",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/UserDataExport"
+                  "$ref": "#/components/schemas/DlqEntryResponse"
                 }
               }
             }
           },
-          "401": {
-            "description": "User not identified from session",
+          "400": {
+            "description": "DLQ not configured",
             "content": {
               "application/json": {
                 "schema": {
@@ -1896,7 +1856,7 @@
             }
           },
           "404": {
-            "description": "User not found",
+            "description": "Entry not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -1906,79 +1866,94 @@
             }
           }
         }
-      }
-    },
-    "/admin/v1/model-pricing": {
-      "get": {
+      },
+      "delete": {
         "tags": [
-          "model-pricing"
+          "dlq"
         ],
-        "summary": "List global model pricing",
-        "operationId": "model_pricing_list_global",
+        "summary": "Delete a DLQ entry.",
+        "operationId": "dlq_delete",
         "parameters": [
           {
-            "name": "limit",
-            "in": "query",
-            "description": "Maximum number of results to return",
-            "required": false,
+            "name": "id",
+            "in": "path",
+            "description": "DLQ entry ID",
+            "required": true,
             "schema": {
-              "type": [
-                "integer",
-                "null"
-              ],
-              "format": "int64"
+              "type": "string",
+              "format": "uuid"
             }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Entry deleted"
           },
-          {
-            "name": "cursor",
-            "in": "query",
-            "description": "Cursor for keyset pagination. Encoded as base64 string.",
-            "required": false,
-            "schema": {
-              "type": [
-                "string",
-                "null"
-              ]
+          "400": {
+            "description": "DLQ not configured",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
             }
           },
-          {
-            "name": "direction",
-            "in": "query",
-            "description": "Pagination direction: \"forward\" (default) or \"backward\".",
-            "required": false,
-            "schema": {
-              "type": [
-                "string",
-                "null"
-              ]
+          "404": {
+            "description": "Entry not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
             }
-          },
+          }
+        }
+      }
+    },
+    "/admin/v1/dlq/{id}/retry": {
+      "post": {
+        "tags": [
+          "dlq"
+        ],
+        "summary": "Retry a specific DLQ entry.",
+        "operationId": "dlq_retry",
+        "parameters": [
           {
-            "name": "include_deleted",
-            "in": "query",
-            "description": "Include soft-deleted records in results",
-            "required": false,
+            "name": "id",
+            "in": "path",
+            "description": "DLQ entry ID",
+            "required": true,
             "schema": {
-              "type": [
-                "boolean",
-                "null"
-              ]
+              "type": "string",
+              "format": "uuid"
             }
           }
         ],
         "responses": {
           "200": {
-            "description": "List of global model pricing",
+            "description": "Retry result",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ModelPricingListResponse"
+                  "$ref": "#/components/schemas/DlqRetryResponse"
                 }
               }
             }
           },
           "400": {
-            "description": "Invalid cursor or direction",
+            "description": "DLQ not configured or invalid entry",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "404": {
+            "description": "Entry not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -1988,18 +1963,20 @@
             }
           }
         }
-      },
+      }
+    },
+    "/admin/v1/dynamic-providers": {
       "post": {
         "tags": [
-          "model-pricing"
+          "dynamic-providers"
         ],
-        "summary": "Create a new model pricing entry",
-        "operationId": "model_pricing_create",
+        "summary": "Create a dynamic provider",
+        "operationId": "dynamic_provider_create",
         "requestBody": {
           "content": {
             "application/json": {
               "schema": {
-                "$ref": "#/components/schemas/CreateModelPricing"
+                "$ref": "#/components/schemas/CreateDynamicProvider"
               }
             }
           },
@@ -2007,17 +1984,17 @@
         },
         "responses": {
           "201": {
-            "description": "Model pricing created",
+            "description": "Dynamic provider created",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/DbModelPricing"
+                  "$ref": "#/components/schemas/DynamicProviderResponse"
                 }
               }
             }
           },
-          "409": {
-            "description": "Conflict (pricing already exists)",
+          "404": {
+            "description": "Owner not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -2029,21 +2006,19 @@
         }
       }
     },
-    "/admin/v1/model-pricing/bulk": {
+    "/admin/v1/dynamic-providers/test-credentials": {
       "post": {
         "tags": [
-          "model-pricing"
+          "dynamic-providers"
         ],
-        "summary": "Bulk upsert model pricing entries",
-        "operationId": "model_pricing_bulk_upsert",
+        "summary": "Test credentials before creating a dynamic provider",
+        "description": "Accepts the same body as the create endpoint but does not persist anything.\nUseful for validating API keys and endpoints before committing.",
+        "operationId": "dynamic_provider_test_credentials",
         "requestBody": {
           "content": {
             "application/json": {
               "schema": {
-                "type": "array",
-                "items": {
-                  "$ref": "#/components/schemas/CreateModelPricing"
-                }
+                "$ref": "#/components/schemas/CreateDynamicProvider"
               }
             }
           },
@@ -2051,98 +2026,60 @@
         },
         "responses": {
           "200": {
-            "description": "Bulk upsert completed",
+            "description": "Connectivity test result",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/BulkUpsertResponse"
+                  "$ref": "#/components/schemas/ConnectivityTestResponse"
                 }
               }
             }
-          }
-        }
-      }
-    },
-    "/admin/v1/model-pricing/provider/{provider}": {
+          },
+          "422": {
+            "description": "Validation error",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/dynamic-providers/{id}": {
       "get": {
         "tags": [
-          "model-pricing"
+          "dynamic-providers"
         ],
-        "summary": "List all pricing for a specific provider (across all scopes)",
-        "operationId": "model_pricing_list_by_provider",
+        "summary": "Get a dynamic provider by ID",
+        "operationId": "dynamic_provider_get",
         "parameters": [
           {
-            "name": "provider",
+            "name": "id",
             "in": "path",
-            "description": "Provider name",
+            "description": "Dynamic provider ID",
             "required": true,
             "schema": {
-              "type": "string"
-            }
-          },
-          {
-            "name": "limit",
-            "in": "query",
-            "description": "Maximum number of results to return",
-            "required": false,
-            "schema": {
-              "type": [
-                "integer",
-                "null"
-              ],
-              "format": "int64"
-            }
-          },
-          {
-            "name": "cursor",
-            "in": "query",
-            "description": "Cursor for keyset pagination. Encoded as base64 string.",
-            "required": false,
-            "schema": {
-              "type": [
-                "string",
-                "null"
-              ]
-            }
-          },
-          {
-            "name": "direction",
-            "in": "query",
-            "description": "Pagination direction: \"forward\" (default) or \"backward\".",
-            "required": false,
-            "schema": {
-              "type": [
-                "string",
-                "null"
-              ]
-            }
-          },
-          {
-            "name": "include_deleted",
-            "in": "query",
-            "description": "Include soft-deleted records in results",
-            "required": false,
-            "schema": {
-              "type": [
-                "boolean",
-                "null"
-              ]
+              "type": "string",
+              "format": "uuid"
             }
           }
         ],
         "responses": {
           "200": {
-            "description": "List of pricing for provider",
+            "description": "Dynamic provider found",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ModelPricingListResponse"
+                  "$ref": "#/components/schemas/DynamicProviderResponse"
                 }
               }
             }
           },
-          "400": {
-            "description": "Invalid cursor or direction",
+          "404": {
+            "description": "Dynamic provider not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -2152,51 +2089,52 @@
             }
           }
         }
-      }
-    },
-    "/admin/v1/model-pricing/upsert": {
-      "post": {
+      },
+      "delete": {
         "tags": [
-          "model-pricing"
+          "dynamic-providers"
         ],
-        "summary": "Upsert model pricing (create or update based on owner/provider/model)",
-        "operationId": "model_pricing_upsert",
-        "requestBody": {
-          "content": {
-            "application/json": {
-              "schema": {
-                "$ref": "#/components/schemas/CreateModelPricing"
-              }
+        "summary": "Delete a dynamic provider",
+        "operationId": "dynamic_provider_delete",
+        "parameters": [
+          {
+            "name": "id",
+            "in": "path",
+            "description": "Dynamic provider ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
             }
-          },
-          "required": true
-        },
+          }
+        ],
         "responses": {
           "200": {
-            "description": "Model pricing upserted",
+            "description": "Dynamic provider deleted"
+          },
+          "404": {
+            "description": "Dynamic provider not found",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/DbModelPricing"
+                  "$ref": "#/components/schemas/ErrorResponse"
                 }
               }
             }
           }
         }
-      }
-    },
-    "/admin/v1/model-pricing/{id}": {
-      "get": {
+      },
+      "patch": {
         "tags": [
-          "model-pricing"
+          "dynamic-providers"
         ],
-        "summary": "Get a model pricing entry by ID",
-        "operationId": "model_pricing_get",
+        "summary": "Update a dynamic provider",
+        "operationId": "dynamic_provider_update",
         "parameters": [
           {
             "name": "id",
             "in": "path",
-            "description": "Model pricing ID",
+            "description": "Dynamic provider ID",
             "required": true,
             "schema": {
               "type": "string",
@@ -2204,19 +2142,29 @@
             }
           }
         ],
+        "requestBody": {
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/UpdateDynamicProvider"
+              }
+            }
+          },
+          "required": true
+        },
         "responses": {
           "200": {
-            "description": "Model pricing found",
+            "description": "Dynamic provider updated",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/DbModelPricing"
+                  "$ref": "#/components/schemas/DynamicProviderResponse"
                 }
               }
             }
           },
           "404": {
-            "description": "Model pricing not found",
+            "description": "Dynamic provider not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -2226,18 +2174,21 @@
             }
           }
         }
-      },
-      "delete": {
+      }
+    },
+    "/admin/v1/dynamic-providers/{id}/test": {
+      "post": {
         "tags": [
-          "model-pricing"
+          "dynamic-providers"
         ],
-        "summary": "Delete a model pricing entry",
-        "operationId": "model_pricing_delete",
+        "summary": "Test connectivity for an existing dynamic provider",
+        "description": "Sends a lightweight request to the provider to verify the API key and endpoint are working.",
+        "operationId": "dynamic_provider_test",
         "parameters": [
           {
             "name": "id",
             "in": "path",
-            "description": "Model pricing ID",
+            "description": "Dynamic provider ID",
             "required": true,
             "schema": {
               "type": "string",
@@ -2247,10 +2198,17 @@
         ],
         "responses": {
           "200": {
-            "description": "Model pricing deleted"
+            "description": "Connectivity test result",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ConnectivityTestResponse"
+                }
+              }
+            }
           },
           "404": {
-            "description": "Model pricing not found",
+            "description": "Provider not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -2260,48 +2218,39 @@
             }
           }
         }
-      },
-      "patch": {
+      }
+    },
+    "/admin/v1/me": {
+      "delete": {
         "tags": [
-          "model-pricing"
-        ],
-        "summary": "Update a model pricing entry",
-        "operationId": "model_pricing_update",
-        "parameters": [
-          {
-            "name": "id",
-            "in": "path",
-            "description": "Model pricing ID",
-            "required": true,
-            "schema": {
-              "type": "string",
-              "format": "uuid"
-            }
-          }
+          "me"
         ],
-        "requestBody": {
-          "content": {
-            "application/json": {
-              "schema": {
-                "$ref": "#/components/schemas/UpdateModelPricing"
+        "summary": "Delete current user and all associated data (GDPR Article 17 - Right to Erasure)",
+        "description": "Permanently deletes the authenticated user and all associated data including:\n- User record\n- Organization and project memberships\n- API keys owned by the user\n- Conversations owned by the user\n- Dynamic providers owned by the user\n- Usage records for user's API keys\n\nThis endpoint allows users to delete their own account without admin permissions.\nThe user is identified from the authenticated session.\n\n**Warning:** This operation is irreversible.",
+        "operationId": "me_delete",
+        "responses": {
+          "200": {
+            "description": "User deleted",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/UserDeletionResponse"
+                }
               }
             }
           },
-          "required": true
-        },
-        "responses": {
-          "200": {
-            "description": "Model pricing updated",
+          "401": {
+            "description": "User not identified from session",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/DbModelPricing"
+                  "$ref": "#/components/schemas/ErrorResponse"
                 }
               }
             }
           },
           "404": {
-            "description": "Model pricing not found",
+            "description": "User not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -2313,13 +2262,13 @@
         }
       }
     },
-    "/admin/v1/organizations": {
+    "/admin/v1/me/api-keys": {
       "get": {
         "tags": [
-          "organizations"
+          "me"
         ],
-        "summary": "List all organizations",
-        "operationId": "organization_list",
+        "summary": "List current user's API keys",
+        "operationId": "me_api_keys_list",
         "parameters": [
           {
             "name": "limit",
@@ -2373,27 +2322,17 @@
         ],
         "responses": {
           "200": {
-            "description": "List of organizations",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/OrganizationListResponse"
-                }
-              }
-            }
-          },
-          "400": {
-            "description": "Invalid cursor or direction",
+            "description": "List of user's API keys",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "$ref": "#/components/schemas/ApiKeyListResponse"
                 }
               }
             }
           },
-          "403": {
-            "description": "Access denied",
+          "401": {
+            "description": "User not identified from session",
             "content": {
               "application/json": {
                 "schema": {
@@ -2406,15 +2345,15 @@
       },
       "post": {
         "tags": [
-          "organizations"
+          "me"
         ],
-        "summary": "Create an organization",
-        "operationId": "organization_create",
+        "summary": "Create an API key for the current user",
+        "operationId": "me_api_keys_create",
         "requestBody": {
           "content": {
             "application/json": {
               "schema": {
-                "$ref": "#/components/schemas/CreateOrganization"
+                "$ref": "#/components/schemas/CreateSelfServiceApiKey"
               }
             }
           },
@@ -2422,17 +2361,17 @@
         },
         "responses": {
           "201": {
-            "description": "Organization created",
+            "description": "API key created. Store the key value securely - it won't be shown again.",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/Organization"
+                  "$ref": "#/components/schemas/CreatedApiKey"
                 }
               }
             }
           },
-          "403": {
-            "description": "Access denied",
+          "401": {
+            "description": "User not identified from session",
             "content": {
               "application/json": {
                 "schema": {
@@ -2441,8 +2380,8 @@
               }
             }
           },
-          "409": {
-            "description": "Conflict (slug already exists)",
+          "422": {
+            "description": "API key limit exceeded or validation error",
             "content": {
               "application/json": {
                 "schema": {
@@ -2454,52 +2393,38 @@
         }
       }
     },
-    "/admin/v1/organizations/{org_slug}/access-report": {
+    "/admin/v1/me/api-keys/{key_id}": {
       "get": {
         "tags": [
-          "access-reviews"
+          "me"
         ],
-        "summary": "Get access report for a specific organization",
-        "description": "Returns a comprehensive access report for the specified organization including:\n- All org members with their roles and project access\n- All API keys scoped to the organization or its projects\n- Recent access grant history from audit logs\n- Summary statistics\n\nUse `format=csv` for CSV export suitable for auditors and spreadsheets.",
-        "operationId": "org_access_report",
+        "summary": "Get an API key by ID (current user only)",
+        "operationId": "me_api_keys_get",
         "parameters": [
           {
-            "name": "org_slug",
+            "name": "key_id",
             "in": "path",
-            "description": "Organization slug",
+            "description": "API key ID",
             "required": true,
             "schema": {
-              "type": "string"
-            }
-          },
-          {
-            "name": "format",
-            "in": "query",
-            "description": "Export format (json or csv)",
-            "required": false,
-            "schema": {
-              "oneOf": [
-                {
-                  "$ref": "#/components/schemas/ExportFormat"
-                }
-              ],
-              "default": "json"
+              "type": "string",
+              "format": "uuid"
             }
           }
         ],
         "responses": {
           "200": {
-            "description": "Organization access report (JSON or CSV based on format parameter)",
+            "description": "API key found",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/OrgAccessReportResponse"
+                  "$ref": "#/components/schemas/ApiKey"
                 }
               }
             }
           },
-          "403": {
-            "description": "Access denied",
+          "404": {
+            "description": "API key not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -2507,9 +2432,33 @@
                 }
               }
             }
+          }
+        }
+      },
+      "delete": {
+        "tags": [
+          "me"
+        ],
+        "summary": "Revoke an API key (current user only)",
+        "operationId": "me_api_keys_revoke",
+        "parameters": [
+          {
+            "name": "key_id",
+            "in": "path",
+            "description": "API key ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "API key revoked"
           },
           "404": {
-            "description": "Organization not found",
+            "description": "API key not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -2521,86 +2470,49 @@
         }
       }
     },
-    "/admin/v1/organizations/{org_slug}/api-keys": {
-      "get": {
+    "/admin/v1/me/api-keys/{key_id}/rotate": {
+      "post": {
         "tags": [
-          "api-keys"
+          "me"
         ],
-        "summary": "List API keys by organization",
-        "operationId": "api_key_list_by_org",
+        "summary": "Rotate an API key (current user only)",
+        "description": "Creates a new API key with the same settings as the old key and sets a grace period\non the old key. During the grace period, both keys are valid.",
+        "operationId": "me_api_keys_rotate",
         "parameters": [
           {
-            "name": "org_slug",
+            "name": "key_id",
             "in": "path",
-            "description": "Organization slug",
+            "description": "API key ID to rotate",
             "required": true,
             "schema": {
-              "type": "string"
-            }
-          },
-          {
-            "name": "limit",
-            "in": "query",
-            "description": "Maximum number of results to return",
-            "required": false,
-            "schema": {
-              "type": [
-                "integer",
-                "null"
-              ],
-              "format": "int64"
-            }
-          },
-          {
-            "name": "cursor",
-            "in": "query",
-            "description": "Cursor for keyset pagination. Encoded as base64 string.",
-            "required": false,
-            "schema": {
-              "type": [
-                "string",
-                "null"
-              ]
-            }
-          },
-          {
-            "name": "direction",
-            "in": "query",
-            "description": "Pagination direction: \"forward\" (default) or \"backward\".",
-            "required": false,
-            "schema": {
-              "type": [
-                "string",
-                "null"
-              ]
-            }
-          },
-          {
-            "name": "include_deleted",
-            "in": "query",
-            "description": "Include soft-deleted records in results",
-            "required": false,
-            "schema": {
-              "type": [
-                "boolean",
-                "null"
-              ]
+              "type": "string",
+              "format": "uuid"
             }
           }
         ],
+        "requestBody": {
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/RotateApiKeyRequest"
+              }
+            }
+          },
+          "required": true
+        },
         "responses": {
-          "200": {
-            "description": "List of API keys",
+          "201": {
+            "description": "API key rotated. Store the new key value securely.",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ApiKeyListResponse"
+                  "$ref": "#/components/schemas/CreatedApiKey"
                 }
               }
             }
           },
           "400": {
-            "description": "Invalid cursor or direction",
+            "description": "Invalid grace period",
             "content": {
               "application/json": {
                 "schema": {
@@ -2610,7 +2522,17 @@
             }
           },
           "404": {
-            "description": "Organization not found",
+            "description": "API key not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "409": {
+            "description": "API key cannot be rotated",
             "content": {
               "application/json": {
                 "schema": {
@@ -2622,86 +2544,48 @@
         }
       }
     },
-    "/admin/v1/organizations/{org_slug}/dynamic-providers": {
+    "/admin/v1/me/built-in-providers": {
       "get": {
         "tags": [
-          "dynamic-providers"
+          "me"
         ],
-        "summary": "List dynamic providers by organization",
-        "operationId": "dynamic_provider_list_by_org",
-        "parameters": [
-          {
-            "name": "org_slug",
-            "in": "path",
-            "description": "Organization slug",
-            "required": true,
-            "schema": {
-              "type": "string"
-            }
-          },
-          {
-            "name": "limit",
-            "in": "query",
-            "description": "Maximum number of results to return",
-            "required": false,
-            "schema": {
-              "type": [
-                "integer",
-                "null"
-              ],
-              "format": "int64"
-            }
-          },
-          {
-            "name": "cursor",
-            "in": "query",
-            "description": "Cursor for keyset pagination. Encoded as base64 string.",
-            "required": false,
-            "schema": {
-              "type": [
-                "string",
-                "null"
-              ]
-            }
-          },
-          {
-            "name": "direction",
-            "in": "query",
-            "description": "Pagination direction: \"forward\" (default) or \"backward\".",
-            "required": false,
-            "schema": {
-              "type": [
-                "string",
-                "null"
-              ]
-            }
-          },
-          {
-            "name": "include_deleted",
-            "in": "query",
-            "description": "Include soft-deleted records in results",
-            "required": false,
-            "schema": {
-              "type": [
-                "boolean",
-                "null"
-              ]
+        "summary": "List built-in providers from the gateway configuration",
+        "operationId": "me_built_in_providers_list",
+        "responses": {
+          "200": {
+            "description": "List of built-in providers",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/BuiltInProvidersResponse"
+                }
+              }
             }
           }
+        }
+      }
+    },
+    "/admin/v1/me/export": {
+      "get": {
+        "tags": [
+          "me"
         ],
+        "summary": "Export current user's data (GDPR Article 15 - Right of Access)",
+        "description": "Exports all personal data associated with the authenticated user including:\n- User profile\n- Organization and project memberships\n- API keys (excluding sensitive hash)\n- Conversations\n- Usage summary\n- Audit logs where user was the actor\n\nThis endpoint allows users to export their own data without admin permissions.\nThe user is identified from the authenticated session.",
+        "operationId": "me_export",
         "responses": {
           "200": {
-            "description": "List of dynamic providers",
+            "description": "User data export",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/DynamicProviderListResponse"
+                  "$ref": "#/components/schemas/UserDataExport"
                 }
               }
             }
           },
-          "400": {
-            "description": "Invalid cursor or direction",
+          "401": {
+            "description": "User not identified from session",
             "content": {
               "application/json": {
                 "schema": {
@@ -2711,7 +2595,7 @@
             }
           },
           "404": {
-            "description": "Organization not found",
+            "description": "User not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -2723,23 +2607,14 @@
         }
       }
     },
-    "/admin/v1/organizations/{org_slug}/members": {
+    "/admin/v1/me/providers": {
       "get": {
         "tags": [
-          "users"
+          "me"
         ],
-        "summary": "List organization members",
-        "operationId": "org_member_list",
+        "summary": "List current user's dynamic providers",
+        "operationId": "me_providers_list",
         "parameters": [
-          {
-            "name": "org_slug",
-            "in": "path",
-            "description": "Organization slug",
-            "required": true,
-            "schema": {
-              "type": "string"
-            }
-          },
           {
             "name": "limit",
             "in": "query",
@@ -2792,17 +2667,17 @@
         ],
         "responses": {
           "200": {
-            "description": "List of organization members",
+            "description": "List of user's dynamic providers",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/UserListResponse"
+                  "$ref": "#/components/schemas/SelfServiceProviderListResponse"
                 }
               }
             }
           },
-          "400": {
-            "description": "Invalid cursor or direction",
+          "401": {
+            "description": "User not identified from session",
             "content": {
               "application/json": {
                 "schema": {
@@ -2810,9 +2685,38 @@
                 }
               }
             }
+          }
+        }
+      },
+      "post": {
+        "tags": [
+          "me"
+        ],
+        "summary": "Create a dynamic provider for the current user",
+        "operationId": "me_providers_create",
+        "requestBody": {
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/CreateSelfServiceProvider"
+              }
+            }
           },
-          "403": {
-            "description": "Access denied",
+          "required": true
+        },
+        "responses": {
+          "201": {
+            "description": "Dynamic provider created",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/DynamicProviderResponse"
+                }
+              }
+            }
+          },
+          "401": {
+            "description": "User not identified from session",
             "content": {
               "application/json": {
                 "schema": {
@@ -2821,8 +2725,18 @@
               }
             }
           },
-          "404": {
-            "description": "Organization not found",
+          "409": {
+            "description": "Provider with this name already exists",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "422": {
+            "description": "Provider limit exceeded",
             "content": {
               "application/json": {
                 "schema": {
@@ -2832,50 +2746,39 @@
             }
           }
         }
-      },
+      }
+    },
+    "/admin/v1/me/providers/test-credentials": {
       "post": {
         "tags": [
-          "users"
-        ],
-        "summary": "Add a member to an organization",
-        "operationId": "org_member_add",
-        "parameters": [
-          {
-            "name": "org_slug",
-            "in": "path",
-            "description": "Organization slug",
-            "required": true,
-            "schema": {
-              "type": "string"
-            }
-          }
+          "me"
         ],
+        "summary": "Test credentials before creating a provider",
+        "description": "Accepts the same body as the create endpoint but does not persist anything.\nUseful for validating API keys and endpoints before committing.",
+        "operationId": "me_providers_test_credentials",
         "requestBody": {
           "content": {
             "application/json": {
               "schema": {
-                "$ref": "#/components/schemas/AddMemberRequest"
+                "$ref": "#/components/schemas/CreateSelfServiceProvider"
               }
             }
           },
           "required": true
         },
         "responses": {
-          "201": {
-            "description": "Member added"
-          },
-          "403": {
-            "description": "Access denied",
+          "200": {
+            "description": "Connectivity test result",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "$ref": "#/components/schemas/ConnectivityTestResponse"
                 }
               }
             }
           },
-          "404": {
-            "description": "Organization or user not found",
+          "422": {
+            "description": "Validation error",
             "content": {
               "application/json": {
                 "schema": {
@@ -2887,27 +2790,18 @@
         }
       }
     },
-    "/admin/v1/organizations/{org_slug}/members/{user_id}": {
-      "delete": {
+    "/admin/v1/me/providers/{id}": {
+      "get": {
         "tags": [
-          "users"
+          "me"
         ],
-        "summary": "Remove a member from an organization",
-        "operationId": "org_member_remove",
+        "summary": "Get a dynamic provider by ID (current user only)",
+        "operationId": "me_providers_get",
         "parameters": [
           {
-            "name": "org_slug",
-            "in": "path",
-            "description": "Organization slug",
-            "required": true,
-            "schema": {
-              "type": "string"
-            }
-          },
-          {
-            "name": "user_id",
+            "name": "id",
             "in": "path",
-            "description": "User ID",
+            "description": "Dynamic provider ID",
             "required": true,
             "schema": {
               "type": "string",
@@ -2917,20 +2811,17 @@
         ],
         "responses": {
           "200": {
-            "description": "Member removed"
-          },
-          "403": {
-            "description": "Access denied",
+            "description": "Dynamic provider found",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "$ref": "#/components/schemas/DynamicProviderResponse"
                 }
               }
             }
           },
           "404": {
-            "description": "Organization not found",
+            "description": "Provider not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -2940,88 +2831,126 @@
             }
           }
         }
-      }
-    },
-    "/admin/v1/organizations/{org_slug}/model-pricing": {
-      "get": {
+      },
+      "delete": {
         "tags": [
-          "model-pricing"
+          "me"
         ],
-        "summary": "List model pricing for an organization",
-        "operationId": "model_pricing_list_by_org",
+        "summary": "Delete a dynamic provider (current user only)",
+        "operationId": "me_providers_delete",
         "parameters": [
           {
-            "name": "org_slug",
+            "name": "id",
             "in": "path",
-            "description": "Organization slug",
+            "description": "Dynamic provider ID",
             "required": true,
             "schema": {
-              "type": "string"
+              "type": "string",
+              "format": "uuid"
             }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Provider deleted"
           },
-          {
-            "name": "limit",
-            "in": "query",
-            "description": "Maximum number of results to return",
-            "required": false,
-            "schema": {
-              "type": [
-                "integer",
-                "null"
-              ],
-              "format": "int64"
+          "404": {
+            "description": "Provider not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
             }
-          },
+          }
+        }
+      },
+      "patch": {
+        "tags": [
+          "me"
+        ],
+        "summary": "Update a dynamic provider (current user only)",
+        "operationId": "me_providers_update",
+        "parameters": [
           {
-            "name": "cursor",
-            "in": "query",
-            "description": "Cursor for keyset pagination. Encoded as base64 string.",
-            "required": false,
+            "name": "id",
+            "in": "path",
+            "description": "Dynamic provider ID",
+            "required": true,
             "schema": {
-              "type": [
-                "string",
-                "null"
-              ]
+              "type": "string",
+              "format": "uuid"
+            }
+          }
+        ],
+        "requestBody": {
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/UpdateDynamicProvider"
+              }
             }
           },
-          {
-            "name": "direction",
-            "in": "query",
-            "description": "Pagination direction: \"forward\" (default) or \"backward\".",
-            "required": false,
-            "schema": {
-              "type": [
-                "string",
-                "null"
-              ]
+          "required": true
+        },
+        "responses": {
+          "200": {
+            "description": "Dynamic provider updated",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/DynamicProviderResponse"
+                }
+              }
             }
           },
+          "404": {
+            "description": "Provider not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/me/providers/{id}/test": {
+      "post": {
+        "tags": [
+          "me"
+        ],
+        "summary": "Test connectivity for a dynamic provider (current user only)",
+        "description": "Sends a lightweight request to the provider to verify the API key and endpoint are working.",
+        "operationId": "me_providers_test",
+        "parameters": [
           {
-            "name": "include_deleted",
-            "in": "query",
-            "description": "Include soft-deleted records in results",
-            "required": false,
+            "name": "id",
+            "in": "path",
+            "description": "Dynamic provider ID",
+            "required": true,
             "schema": {
-              "type": [
-                "boolean",
-                "null"
-              ]
+              "type": "string",
+              "format": "uuid"
             }
           }
         ],
         "responses": {
           "200": {
-            "description": "List of organization model pricing",
+            "description": "Connectivity test result",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ModelPricingListResponse"
+                  "$ref": "#/components/schemas/ConnectivityTestResponse"
                 }
               }
             }
           },
-          "400": {
-            "description": "Invalid cursor or direction",
+          "404": {
+            "description": "Provider not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -3029,9 +2958,31 @@
                 }
               }
             }
+          }
+        }
+      }
+    },
+    "/admin/v1/me/sessions": {
+      "get": {
+        "tags": [
+          "me"
+        ],
+        "summary": "List current user's active sessions.",
+        "description": "Returns an empty list if enhanced session management is not enabled.\nThe `enhanced_enabled` field indicates whether session tracking is active.",
+        "operationId": "me_sessions_list",
+        "responses": {
+          "200": {
+            "description": "List of current user's sessions",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/SessionListResponse"
+                }
+              }
+            }
           },
-          "404": {
-            "description": "Organization not found",
+          "401": {
+            "description": "Not authenticated",
             "content": {
               "application/json": {
                 "schema": {
@@ -3043,96 +2994,39 @@
         }
       }
     },
-    "/admin/v1/organizations/{org_slug}/projects": {
-      "get": {
+    "/admin/v1/me/sessions/{session_id}": {
+      "delete": {
         "tags": [
-          "projects"
+          "me"
         ],
-        "summary": "List projects in an organization",
-        "operationId": "project_list",
+        "summary": "Revoke a specific session belonging to the current user.",
+        "description": "Returns success even if the session doesn't exist (idempotent).\nReturns 400 if the session belongs to a different user.",
+        "operationId": "me_sessions_delete_one",
         "parameters": [
           {
-            "name": "org_slug",
+            "name": "session_id",
             "in": "path",
-            "description": "Organization slug",
+            "description": "Session ID to revoke",
             "required": true,
             "schema": {
-              "type": "string"
-            }
-          },
-          {
-            "name": "limit",
-            "in": "query",
-            "description": "Maximum number of results to return",
-            "required": false,
-            "schema": {
-              "type": [
-                "integer",
-                "null"
-              ],
-              "format": "int64"
-            }
-          },
-          {
-            "name": "cursor",
-            "in": "query",
-            "description": "Cursor for keyset pagination. Encoded as base64 string.",
-            "required": false,
-            "schema": {
-              "type": [
-                "string",
-                "null"
-              ]
-            }
-          },
-          {
-            "name": "direction",
-            "in": "query",
-            "description": "Pagination direction: \"forward\" (default) or \"backward\".",
-            "required": false,
-            "schema": {
-              "type": [
-                "string",
-                "null"
-              ]
-            }
-          },
-          {
-            "name": "include_deleted",
-            "in": "query",
-            "description": "Include soft-deleted records in results",
-            "required": false,
-            "schema": {
-              "type": [
-                "boolean",
-                "null"
-              ]
+              "type": "string",
+              "format": "uuid"
             }
           }
         ],
         "responses": {
           "200": {
-            "description": "List of projects",
+            "description": "Session revoked",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ProjectListResponse"
+                  "$ref": "#/components/schemas/SessionsRevokedResponse"
                 }
               }
             }
           },
           "400": {
-            "description": "Invalid cursor or direction",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
-            }
-          },
-          "403": {
-            "description": "Access denied",
+            "description": "Session does not belong to current user",
             "content": {
               "application/json": {
                 "schema": {
@@ -3141,8 +3035,8 @@
               }
             }
           },
-          "404": {
-            "description": "Organization not found",
+          "401": {
+            "description": "Not authenticated",
             "content": {
               "application/json": {
                 "schema": {
@@ -3152,67 +3046,55 @@
             }
           }
         }
-      },
-      "post": {
+      }
+    },
+    "/admin/v1/me/usage": {
+      "get": {
         "tags": [
-          "projects"
+          "me"
         ],
-        "summary": "Create a project in an organization",
-        "operationId": "project_create",
+        "summary": "Get current user's usage summary",
+        "description": "Returns usage data for the authenticated user. Does not require admin role.",
+        "operationId": "me_usage_summary",
         "parameters": [
           {
-            "name": "org_slug",
-            "in": "path",
-            "description": "Organization slug",
-            "required": true,
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
             "schema": {
-              "type": "string"
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
             }
           }
         ],
-        "requestBody": {
-          "content": {
-            "application/json": {
-              "schema": {
-                "$ref": "#/components/schemas/CreateProject"
-              }
-            }
-          },
-          "required": true
-        },
         "responses": {
-          "201": {
-            "description": "Project created",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/Project"
-                }
-              }
-            }
-          },
-          "403": {
-            "description": "Access denied",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
-            }
-          },
-          "404": {
-            "description": "Organization not found",
+          "200": {
+            "description": "Usage summary",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "$ref": "#/components/schemas/UsageSummaryResponse"
                 }
               }
             }
           },
-          "409": {
-            "description": "Conflict (slug already exists)",
+          "401": {
+            "description": "User not identified from session",
             "content": {
               "application/json": {
                 "schema": {
@@ -3224,56 +3106,55 @@
         }
       }
     },
-    "/admin/v1/organizations/{org_slug}/projects/{project_slug}": {
+    "/admin/v1/me/usage/by-date": {
       "get": {
         "tags": [
-          "projects"
+          "me"
         ],
-        "summary": "Get a project by slug",
-        "operationId": "project_get",
+        "summary": "Get current user's usage by date",
+        "operationId": "me_usage_by_date",
         "parameters": [
           {
-            "name": "org_slug",
-            "in": "path",
-            "description": "Organization slug",
-            "required": true,
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
             "schema": {
-              "type": "string"
+              "type": [
+                "string",
+                "null"
+              ]
             }
           },
           {
-            "name": "project_slug",
-            "in": "path",
-            "description": "Project slug",
-            "required": true,
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
             "schema": {
-              "type": "string"
+              "type": [
+                "string",
+                "null"
+              ]
             }
           }
         ],
         "responses": {
           "200": {
-            "description": "Project found",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/Project"
-                }
-              }
-            }
-          },
-          "403": {
-            "description": "Access denied",
+            "description": "Daily usage breakdown",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/DailySpendResponse"
+                  }
                 }
               }
             }
           },
-          "404": {
-            "description": "Organization or project not found",
+          "401": {
+            "description": "User not identified from session",
             "content": {
               "application/json": {
                 "schema": {
@@ -3283,122 +3164,101 @@
             }
           }
         }
-      },
-      "delete": {
+      }
+    },
+    "/admin/v1/me/usage/by-date-model": {
+      "get": {
         "tags": [
-          "projects"
+          "me"
         ],
-        "summary": "Delete a project",
-        "operationId": "project_delete",
+        "summary": "Get current user's usage by date and model",
+        "operationId": "me_usage_by_date_model",
         "parameters": [
           {
-            "name": "org_slug",
-            "in": "path",
-            "description": "Organization slug",
-            "required": true,
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
             "schema": {
-              "type": "string"
+              "type": [
+                "string",
+                "null"
+              ]
             }
           },
           {
-            "name": "project_slug",
-            "in": "path",
-            "description": "Project slug",
-            "required": true,
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
             "schema": {
-              "type": "string"
+              "type": [
+                "string",
+                "null"
+              ]
             }
           }
         ],
         "responses": {
           "200": {
-            "description": "Project deleted"
-          },
-          "403": {
-            "description": "Access denied",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
-            }
-          },
-          "404": {
-            "description": "Organization or project not found",
+            "description": "Daily usage breakdown by model",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/DailyModelSpendResponse"
+                  }
                 }
               }
             }
           }
         }
-      },
-      "patch": {
-        "tags": [
-          "projects"
+      }
+    },
+    "/admin/v1/me/usage/by-date-pricing-source": {
+      "get": {
+        "tags": [
+          "me"
         ],
-        "summary": "Update a project",
-        "operationId": "project_update",
+        "summary": "Get current user's usage by date and pricing source",
+        "operationId": "me_usage_by_date_pricing_source",
         "parameters": [
           {
-            "name": "org_slug",
-            "in": "path",
-            "description": "Organization slug",
-            "required": true,
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
             "schema": {
-              "type": "string"
+              "type": [
+                "string",
+                "null"
+              ]
             }
           },
           {
-            "name": "project_slug",
-            "in": "path",
-            "description": "Project slug",
-            "required": true,
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
             "schema": {
-              "type": "string"
+              "type": [
+                "string",
+                "null"
+              ]
             }
           }
         ],
-        "requestBody": {
-          "content": {
-            "application/json": {
-              "schema": {
-                "$ref": "#/components/schemas/UpdateProject"
-              }
-            }
-          },
-          "required": true
-        },
         "responses": {
           "200": {
-            "description": "Project updated",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/Project"
-                }
-              }
-            }
-          },
-          "403": {
-            "description": "Access denied",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
-            }
-          },
-          "404": {
-            "description": "Organization or project not found",
+            "description": "Daily usage breakdown by pricing source",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/DailyPricingSourceSpendResponse"
+                  }
                 }
               }
             }
@@ -3406,49 +3266,30 @@
         }
       }
     },
-    "/admin/v1/organizations/{org_slug}/projects/{project_slug}/api-keys": {
+    "/admin/v1/me/usage/by-date-provider": {
       "get": {
         "tags": [
-          "api-keys"
+          "me"
         ],
-        "summary": "List API keys by project",
-        "operationId": "api_key_list_by_project",
+        "summary": "Get current user's usage by date and provider",
+        "operationId": "me_usage_by_date_provider",
         "parameters": [
           {
-            "name": "org_slug",
-            "in": "path",
-            "description": "Organization slug",
-            "required": true,
-            "schema": {
-              "type": "string"
-            }
-          },
-          {
-            "name": "project_slug",
-            "in": "path",
-            "description": "Project slug",
-            "required": true,
-            "schema": {
-              "type": "string"
-            }
-          },
-          {
-            "name": "limit",
+            "name": "start_date",
             "in": "query",
-            "description": "Maximum number of results to return",
+            "description": "Start date (YYYY-MM-DD)",
             "required": false,
             "schema": {
               "type": [
-                "integer",
+                "string",
                 "null"
-              ],
-              "format": "int64"
+              ]
             }
           },
           {
-            "name": "cursor",
+            "name": "end_date",
             "in": "query",
-            "description": "Cursor for keyset pagination. Encoded as base64 string.",
+            "description": "End date (YYYY-MM-DD)",
             "required": false,
             "schema": {
               "type": [
@@ -3456,11 +3297,37 @@
                 "null"
               ]
             }
-          },
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Daily usage breakdown by provider",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/DailyProviderSpendResponse"
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/me/usage/by-model": {
+      "get": {
+        "tags": [
+          "me"
+        ],
+        "summary": "Get current user's usage by model",
+        "operationId": "me_usage_by_model",
+        "parameters": [
           {
-            "name": "direction",
+            "name": "start_date",
             "in": "query",
-            "description": "Pagination direction: \"forward\" (default) or \"backward\".",
+            "description": "Start date (YYYY-MM-DD)",
             "required": false,
             "schema": {
               "type": [
@@ -3470,13 +3337,13 @@
             }
           },
           {
-            "name": "include_deleted",
+            "name": "end_date",
             "in": "query",
-            "description": "Include soft-deleted records in results",
+            "description": "End date (YYYY-MM-DD)",
             "required": false,
             "schema": {
               "type": [
-                "boolean",
+                "string",
                 "null"
               ]
             }
@@ -3484,27 +3351,20 @@
         ],
         "responses": {
           "200": {
-            "description": "List of API keys",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ApiKeyListResponse"
-                }
-              }
-            }
-          },
-          "400": {
-            "description": "Invalid cursor or direction",
+            "description": "Usage breakdown by model",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/ModelSpendResponse"
+                  }
                 }
               }
             }
           },
-          "404": {
-            "description": "Organization or project not found",
+          "401": {
+            "description": "User not identified from session",
             "content": {
               "application/json": {
                 "schema": {
@@ -3516,49 +3376,30 @@
         }
       }
     },
-    "/admin/v1/organizations/{org_slug}/projects/{project_slug}/conversations": {
+    "/admin/v1/me/usage/by-pricing-source": {
       "get": {
         "tags": [
-          "conversations"
+          "me"
         ],
-        "summary": "List conversations by project",
-        "operationId": "conversation_list_by_project",
+        "summary": "Get current user's usage by pricing source",
+        "operationId": "me_usage_by_pricing_source",
         "parameters": [
           {
-            "name": "org_slug",
-            "in": "path",
-            "description": "Organization slug",
-            "required": true,
-            "schema": {
-              "type": "string"
-            }
-          },
-          {
-            "name": "project_slug",
-            "in": "path",
-            "description": "Project slug",
-            "required": true,
-            "schema": {
-              "type": "string"
-            }
-          },
-          {
-            "name": "limit",
+            "name": "start_date",
             "in": "query",
-            "description": "Maximum number of results to return",
+            "description": "Start date (YYYY-MM-DD)",
             "required": false,
             "schema": {
               "type": [
-                "integer",
+                "string",
                 "null"
-              ],
-              "format": "int64"
+              ]
             }
           },
           {
-            "name": "cursor",
+            "name": "end_date",
             "in": "query",
-            "description": "Cursor for keyset pagination. Encoded as base64 string.",
+            "description": "End date (YYYY-MM-DD)",
             "required": false,
             "schema": {
               "type": [
@@ -3566,11 +3407,37 @@
                 "null"
               ]
             }
-          },
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Usage breakdown by pricing source",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/PricingSourceSpendResponse"
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/me/usage/by-provider": {
+      "get": {
+        "tags": [
+          "me"
+        ],
+        "summary": "Get current user's usage by provider",
+        "operationId": "me_usage_by_provider",
+        "parameters": [
           {
-            "name": "direction",
+            "name": "start_date",
             "in": "query",
-            "description": "Pagination direction: \"forward\" (default) or \"backward\".",
+            "description": "Start date (YYYY-MM-DD)",
             "required": false,
             "schema": {
               "type": [
@@ -3580,13 +3447,13 @@
             }
           },
           {
-            "name": "include_deleted",
+            "name": "end_date",
             "in": "query",
-            "description": "Include soft-deleted records in results",
+            "description": "End date (YYYY-MM-DD)",
             "required": false,
             "schema": {
               "type": [
-                "boolean",
+                "string",
                 "null"
               ]
             }
@@ -3594,27 +3461,20 @@
         ],
         "responses": {
           "200": {
-            "description": "List of conversations",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ConversationListResponse"
-                }
-              }
-            }
-          },
-          "400": {
-            "description": "Invalid cursor or direction",
+            "description": "Usage breakdown by provider",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/ProviderSpendResponse"
+                  }
                 }
               }
             }
           },
-          "404": {
-            "description": "Organization or project not found",
+          "401": {
+            "description": "User not identified from session",
             "content": {
               "application/json": {
                 "schema": {
@@ -3626,171 +3486,158 @@
         }
       }
     },
-    "/admin/v1/organizations/{org_slug}/projects/{project_slug}/dynamic-providers": {
+    "/admin/v1/me/usage/logs": {
       "get": {
         "tags": [
-          "dynamic-providers"
+          "me"
         ],
-        "summary": "List dynamic providers by project",
-        "operationId": "dynamic_provider_list_by_project",
+        "summary": "List current user's usage logs",
+        "operationId": "me_usage_log_list",
         "parameters": [
           {
-            "name": "org_slug",
-            "in": "path",
-            "description": "Organization slug",
-            "required": true,
+            "name": "org_id",
+            "in": "query",
+            "required": false,
             "schema": {
-              "type": "string"
+              "type": [
+                "string",
+                "null"
+              ],
+              "format": "uuid"
             }
           },
           {
-            "name": "project_slug",
-            "in": "path",
-            "description": "Project slug",
-            "required": true,
+            "name": "user_id",
+            "in": "query",
+            "required": false,
             "schema": {
-              "type": "string"
+              "type": [
+                "string",
+                "null"
+              ],
+              "format": "uuid"
             }
           },
           {
-            "name": "limit",
+            "name": "project_id",
             "in": "query",
-            "description": "Maximum number of results to return",
             "required": false,
             "schema": {
               "type": [
-                "integer",
+                "string",
                 "null"
               ],
-              "format": "int64"
+              "format": "uuid"
             }
           },
           {
-            "name": "cursor",
+            "name": "team_id",
             "in": "query",
-            "description": "Cursor for keyset pagination. Encoded as base64 string.",
             "required": false,
             "schema": {
               "type": [
                 "string",
                 "null"
-              ]
+              ],
+              "format": "uuid"
             }
           },
           {
-            "name": "direction",
+            "name": "api_key_id",
             "in": "query",
-            "description": "Pagination direction: \"forward\" (default) or \"backward\".",
             "required": false,
             "schema": {
               "type": [
                 "string",
                 "null"
-              ]
+              ],
+              "format": "uuid"
             }
           },
           {
-            "name": "include_deleted",
+            "name": "service_account_id",
             "in": "query",
-            "description": "Include soft-deleted records in results",
             "required": false,
             "schema": {
               "type": [
-                "boolean",
+                "string",
                 "null"
-              ]
-            }
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "List of dynamic providers",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/DynamicProviderListResponse"
-                }
-              }
+              ],
+              "format": "uuid"
             }
           },
-          "400": {
-            "description": "Invalid cursor or direction",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
+          {
+            "name": "model",
+            "in": "query",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
             }
           },
-          "404": {
-            "description": "Organization or project not found",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
-            }
-          }
-        }
-      }
-    },
-    "/admin/v1/organizations/{org_slug}/projects/{project_slug}/members": {
-      "get": {
-        "tags": [
-          "users"
-        ],
-        "summary": "List project members",
-        "operationId": "project_member_list",
-        "parameters": [
           {
-            "name": "org_slug",
-            "in": "path",
-            "description": "Organization slug",
-            "required": true,
+            "name": "provider",
+            "in": "query",
+            "required": false,
             "schema": {
-              "type": "string"
+              "type": [
+                "string",
+                "null"
+              ]
             }
           },
           {
-            "name": "project_slug",
-            "in": "path",
-            "description": "Project slug",
-            "required": true,
+            "name": "provider_source",
+            "in": "query",
+            "required": false,
             "schema": {
-              "type": "string"
+              "type": [
+                "string",
+                "null"
+              ]
             }
           },
           {
-            "name": "limit",
+            "name": "from",
             "in": "query",
-            "description": "Maximum number of results to return",
             "required": false,
             "schema": {
               "type": [
-                "integer",
+                "string",
                 "null"
               ],
-              "format": "int64"
+              "format": "date-time"
             }
           },
           {
-            "name": "cursor",
+            "name": "to",
             "in": "query",
-            "description": "Cursor for keyset pagination. Encoded as base64 string.",
             "required": false,
             "schema": {
               "type": [
                 "string",
                 "null"
-              ]
+              ],
+              "format": "date-time"
             }
           },
           {
-            "name": "direction",
+            "name": "limit",
+            "in": "query",
+            "required": false,
+            "schema": {
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "int64"
+            }
+          },
+          {
+            "name": "cursor",
             "in": "query",
-            "description": "Pagination direction: \"forward\" (default) or \"backward\".",
             "required": false,
             "schema": {
               "type": [
@@ -3800,13 +3647,12 @@
             }
           },
           {
-            "name": "include_deleted",
+            "name": "direction",
             "in": "query",
-            "description": "Include soft-deleted records in results",
             "required": false,
             "schema": {
               "type": [
-                "boolean",
+                "string",
                 "null"
               ]
             }
@@ -3814,200 +3660,182 @@
         ],
         "responses": {
           "200": {
-            "description": "List of project members",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/UserListResponse"
-                }
-              }
-            }
-          },
-          "400": {
-            "description": "Invalid cursor or direction",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
-            }
-          },
-          "403": {
-            "description": "Access denied",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
-            }
-          },
-          "404": {
-            "description": "Organization or project not found",
+            "description": "List of usage log records",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "$ref": "#/components/schemas/UsageLogListResponse"
                 }
               }
             }
           }
         }
-      },
-      "post": {
+      }
+    },
+    "/admin/v1/me/usage/logs/export": {
+      "get": {
         "tags": [
-          "users"
+          "me"
         ],
-        "summary": "Add a member to a project",
-        "operationId": "project_member_add",
+        "summary": "Export current user's usage logs",
+        "operationId": "me_usage_log_export",
         "parameters": [
           {
-            "name": "org_slug",
-            "in": "path",
-            "description": "Organization slug",
-            "required": true,
+            "name": "org_id",
+            "in": "query",
+            "required": false,
             "schema": {
-              "type": "string"
+              "type": [
+                "string",
+                "null"
+              ],
+              "format": "uuid"
             }
           },
           {
-            "name": "project_slug",
-            "in": "path",
-            "description": "Project slug",
-            "required": true,
+            "name": "user_id",
+            "in": "query",
+            "required": false,
             "schema": {
-              "type": "string"
-            }
-          }
-        ],
-        "requestBody": {
-          "content": {
-            "application/json": {
-              "schema": {
-                "$ref": "#/components/schemas/AddMemberRequest"
-              }
+              "type": [
+                "string",
+                "null"
+              ],
+              "format": "uuid"
             }
           },
-          "required": true
-        },
-        "responses": {
-          "201": {
-            "description": "Member added"
-          },
-          "403": {
-            "description": "Access denied",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
+          {
+            "name": "project_id",
+            "in": "query",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ],
+              "format": "uuid"
             }
           },
-          "404": {
-            "description": "Organization, project, or user not found",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
-            }
-          }
-        }
-      }
-    },
-    "/admin/v1/organizations/{org_slug}/projects/{project_slug}/members/{user_id}": {
-      "delete": {
-        "tags": [
-          "users"
-        ],
-        "summary": "Remove a member from a project",
-        "operationId": "project_member_remove",
-        "parameters": [
           {
-            "name": "org_slug",
-            "in": "path",
-            "description": "Organization slug",
-            "required": true,
+            "name": "team_id",
+            "in": "query",
+            "required": false,
             "schema": {
-              "type": "string"
+              "type": [
+                "string",
+                "null"
+              ],
+              "format": "uuid"
             }
           },
           {
-            "name": "project_slug",
-            "in": "path",
-            "description": "Project slug",
-            "required": true,
+            "name": "api_key_id",
+            "in": "query",
+            "required": false,
             "schema": {
-              "type": "string"
+              "type": [
+                "string",
+                "null"
+              ],
+              "format": "uuid"
             }
           },
           {
-            "name": "user_id",
-            "in": "path",
-            "description": "User ID",
-            "required": true,
+            "name": "service_account_id",
+            "in": "query",
+            "required": false,
             "schema": {
-              "type": "string",
+              "type": [
+                "string",
+                "null"
+              ],
               "format": "uuid"
             }
+          },
+          {
+            "name": "model",
+            "in": "query",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "provider",
+            "in": "query",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "provider_source",
+            "in": "query",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "from",
+            "in": "query",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ],
+              "format": "date-time"
+            }
+          },
+          {
+            "name": "to",
+            "in": "query",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ],
+              "format": "date-time"
+            }
+          },
+          {
+            "name": "format",
+            "in": "query",
+            "required": false,
+            "schema": {
+              "$ref": "#/components/schemas/UsageLogExportFormat"
+            }
           }
         ],
         "responses": {
           "200": {
-            "description": "Member removed"
-          },
-          "403": {
-            "description": "Access denied",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
-            }
-          },
-          "404": {
-            "description": "Organization or project not found",
+            "description": "Exported usage logs",
             "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
+              "application/x-ndjson": {}
             }
           }
         }
       }
     },
-    "/admin/v1/organizations/{org_slug}/projects/{project_slug}/model-pricing": {
+    "/admin/v1/model-pricing": {
       "get": {
         "tags": [
           "model-pricing"
         ],
-        "summary": "List model pricing for a project",
-        "operationId": "model_pricing_list_by_project",
+        "summary": "List global model pricing",
+        "operationId": "model_pricing_list_global",
         "parameters": [
-          {
-            "name": "org_slug",
-            "in": "path",
-            "description": "Organization slug",
-            "required": true,
-            "schema": {
-              "type": "string"
-            }
-          },
-          {
-            "name": "project_slug",
-            "in": "path",
-            "description": "Project slug",
-            "required": true,
-            "schema": {
-              "type": "string"
-            }
-          },
           {
             "name": "limit",
             "in": "query",
@@ -4060,7 +3888,7 @@
         ],
         "responses": {
           "200": {
-            "description": "List of project model pricing",
+            "description": "List of global model pricing",
             "content": {
               "application/json": {
                 "schema": {
@@ -4078,9 +3906,38 @@
                 }
               }
             }
+          }
+        }
+      },
+      "post": {
+        "tags": [
+          "model-pricing"
+        ],
+        "summary": "Create a new model pricing entry",
+        "operationId": "model_pricing_create",
+        "requestBody": {
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/CreateModelPricing"
+              }
+            }
           },
-          "404": {
-            "description": "Organization or project not found",
+          "required": true
+        },
+        "responses": {
+          "201": {
+            "description": "Model pricing created",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/DbModelPricing"
+                }
+              }
+            }
+          },
+          "409": {
+            "description": "Conflict (pricing already exists)",
             "content": {
               "application/json": {
                 "schema": {
@@ -4092,27 +3949,52 @@
         }
       }
     },
-    "/admin/v1/organizations/{org_slug}/projects/{project_slug}/prompts": {
-      "get": {
+    "/admin/v1/model-pricing/bulk": {
+      "post": {
         "tags": [
-          "prompts"
+          "model-pricing"
         ],
-        "summary": "List prompts by project",
-        "operationId": "prompt_list_by_project",
-        "parameters": [
-          {
-            "name": "org_slug",
-            "in": "path",
-            "description": "Organization slug",
-            "required": true,
-            "schema": {
-              "type": "string"
+        "summary": "Bulk upsert model pricing entries",
+        "operationId": "model_pricing_bulk_upsert",
+        "requestBody": {
+          "content": {
+            "application/json": {
+              "schema": {
+                "type": "array",
+                "items": {
+                  "$ref": "#/components/schemas/CreateModelPricing"
+                }
+              }
             }
           },
+          "required": true
+        },
+        "responses": {
+          "200": {
+            "description": "Bulk upsert completed",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/BulkUpsertResponse"
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/model-pricing/provider/{provider}": {
+      "get": {
+        "tags": [
+          "model-pricing"
+        ],
+        "summary": "List all pricing for a specific provider (across all scopes)",
+        "operationId": "model_pricing_list_by_provider",
+        "parameters": [
           {
-            "name": "project_slug",
+            "name": "provider",
             "in": "path",
-            "description": "Project slug",
+            "description": "Provider name",
             "required": true,
             "schema": {
               "type": "string"
@@ -4170,11 +4052,11 @@
         ],
         "responses": {
           "200": {
-            "description": "List of prompts",
+            "description": "List of pricing for provider",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/PromptListResponse"
+                  "$ref": "#/components/schemas/ModelPricingListResponse"
                 }
               }
             }
@@ -4188,84 +4070,73 @@
                 }
               }
             }
-          },
-          "404": {
-            "description": "Organization or project not found",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
-            }
           }
         }
       }
     },
-    "/admin/v1/organizations/{org_slug}/projects/{project_slug}/usage": {
-      "get": {
+    "/admin/v1/model-pricing/upsert": {
+      "post": {
         "tags": [
-          "usage"
+          "model-pricing"
         ],
-        "summary": "Get usage summary for a project",
-        "operationId": "usage_get_project_summary",
-        "parameters": [
-          {
-            "name": "org_slug",
-            "in": "path",
-            "description": "Organization slug",
-            "required": true,
-            "schema": {
-              "type": "string"
+        "summary": "Upsert model pricing (create or update based on owner/provider/model)",
+        "operationId": "model_pricing_upsert",
+        "requestBody": {
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/CreateModelPricing"
+              }
             }
           },
+          "required": true
+        },
+        "responses": {
+          "200": {
+            "description": "Model pricing upserted",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/DbModelPricing"
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/model-pricing/{id}": {
+      "get": {
+        "tags": [
+          "model-pricing"
+        ],
+        "summary": "Get a model pricing entry by ID",
+        "operationId": "model_pricing_get",
+        "parameters": [
           {
-            "name": "project_slug",
+            "name": "id",
             "in": "path",
-            "description": "Project slug",
+            "description": "Model pricing ID",
             "required": true,
             "schema": {
-              "type": "string"
-            }
-          },
-          {
-            "name": "start_date",
-            "in": "query",
-            "description": "Start date (YYYY-MM-DD)",
-            "required": false,
-            "schema": {
-              "type": [
-                "string",
-                "null"
-              ]
-            }
-          },
-          {
-            "name": "end_date",
-            "in": "query",
-            "description": "End date (YYYY-MM-DD)",
-            "required": false,
-            "schema": {
-              "type": [
-                "string",
-                "null"
-              ]
+              "type": "string",
+              "format": "uuid"
             }
           }
         ],
         "responses": {
           "200": {
-            "description": "Usage summary",
+            "description": "Model pricing found",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/UsageSummaryResponse"
+                  "$ref": "#/components/schemas/DbModelPricing"
                 }
               }
             }
           },
           "404": {
-            "description": "Project not found",
+            "description": "Model pricing not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -4275,75 +4146,82 @@
             }
           }
         }
-      }
-    },
-    "/admin/v1/organizations/{org_slug}/projects/{project_slug}/usage/by-date": {
-      "get": {
+      },
+      "delete": {
         "tags": [
-          "usage"
+          "model-pricing"
         ],
-        "summary": "Get usage by date for a project",
-        "operationId": "usage_get_project_by_date",
+        "summary": "Delete a model pricing entry",
+        "operationId": "model_pricing_delete",
         "parameters": [
           {
-            "name": "org_slug",
+            "name": "id",
             "in": "path",
-            "description": "Organization slug",
+            "description": "Model pricing ID",
             "required": true,
             "schema": {
-              "type": "string"
+              "type": "string",
+              "format": "uuid"
             }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Model pricing deleted"
           },
+          "404": {
+            "description": "Model pricing not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        }
+      },
+      "patch": {
+        "tags": [
+          "model-pricing"
+        ],
+        "summary": "Update a model pricing entry",
+        "operationId": "model_pricing_update",
+        "parameters": [
           {
-            "name": "project_slug",
+            "name": "id",
             "in": "path",
-            "description": "Project slug",
+            "description": "Model pricing ID",
             "required": true,
             "schema": {
-              "type": "string"
-            }
-          },
-          {
-            "name": "start_date",
-            "in": "query",
-            "description": "Start date (YYYY-MM-DD)",
-            "required": false,
-            "schema": {
-              "type": [
-                "string",
-                "null"
-              ]
-            }
-          },
-          {
-            "name": "end_date",
-            "in": "query",
-            "description": "End date (YYYY-MM-DD)",
-            "required": false,
-            "schema": {
-              "type": [
-                "string",
-                "null"
-              ]
+              "type": "string",
+              "format": "uuid"
             }
           }
         ],
+        "requestBody": {
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/UpdateModelPricing"
+              }
+            }
+          },
+          "required": true
+        },
         "responses": {
           "200": {
-            "description": "Daily usage breakdown",
+            "description": "Model pricing updated",
             "content": {
               "application/json": {
                 "schema": {
-                  "type": "array",
-                  "items": {
-                    "$ref": "#/components/schemas/DailySpendResponse"
-                  }
+                  "$ref": "#/components/schemas/DbModelPricing"
                 }
               }
             }
           },
           "404": {
-            "description": "Project not found",
+            "description": "Model pricing not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -4355,36 +4233,43 @@
         }
       }
     },
-    "/admin/v1/organizations/{org_slug}/projects/{project_slug}/usage/by-model": {
+    "/admin/v1/organizations": {
       "get": {
         "tags": [
-          "usage"
+          "organizations"
         ],
-        "summary": "Get usage by model for a project",
-        "operationId": "usage_get_project_by_model",
+        "summary": "List all organizations",
+        "operationId": "organization_list",
         "parameters": [
           {
-            "name": "org_slug",
-            "in": "path",
-            "description": "Organization slug",
-            "required": true,
+            "name": "limit",
+            "in": "query",
+            "description": "Maximum number of results to return",
+            "required": false,
             "schema": {
-              "type": "string"
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "int64"
             }
           },
           {
-            "name": "project_slug",
-            "in": "path",
-            "description": "Project slug",
-            "required": true,
+            "name": "cursor",
+            "in": "query",
+            "description": "Cursor for keyset pagination. Encoded as base64 string.",
+            "required": false,
             "schema": {
-              "type": "string"
+              "type": [
+                "string",
+                "null"
+              ]
             }
           },
           {
-            "name": "start_date",
+            "name": "direction",
             "in": "query",
-            "description": "Start date (YYYY-MM-DD)",
+            "description": "Pagination direction: \"forward\" (default) or \"backward\".",
             "required": false,
             "schema": {
               "type": [
@@ -4394,13 +4279,13 @@
             }
           },
           {
-            "name": "end_date",
+            "name": "include_deleted",
             "in": "query",
-            "description": "End date (YYYY-MM-DD)",
+            "description": "Include soft-deleted records in results",
             "required": false,
             "schema": {
               "type": [
-                "string",
+                "boolean",
                 "null"
               ]
             }
@@ -4408,20 +4293,27 @@
         ],
         "responses": {
           "200": {
-            "description": "Usage breakdown by model",
+            "description": "List of organizations",
             "content": {
               "application/json": {
                 "schema": {
-                  "type": "array",
-                  "items": {
-                    "$ref": "#/components/schemas/ModelSpendResponse"
-                  }
+                  "$ref": "#/components/schemas/OrganizationListResponse"
                 }
               }
             }
           },
-          "404": {
-            "description": "Project not found",
+          "400": {
+            "description": "Invalid cursor or direction",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "403": {
+            "description": "Access denied",
             "content": {
               "application/json": {
                 "schema": {
@@ -4431,75 +4323,113 @@
             }
           }
         }
-      }
-    },
-    "/admin/v1/organizations/{org_slug}/projects/{project_slug}/usage/forecast": {
-      "get": {
+      },
+      "post": {
         "tags": [
-          "usage"
+          "organizations"
         ],
-        "summary": "Get cost forecast for a project",
-        "description": "Uses historical usage data across all API keys in the project to predict future spending.\nReturns average daily spend, confidence intervals, and time series forecasts.",
-        "operationId": "usage_get_project_forecast",
-        "parameters": [
-          {
-            "name": "org_slug",
-            "in": "path",
-            "description": "Organization slug",
-            "required": true,
-            "schema": {
-              "type": "string"
+        "summary": "Create an organization",
+        "operationId": "organization_create",
+        "requestBody": {
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/CreateOrganization"
+              }
+            }
+          },
+          "required": true
+        },
+        "responses": {
+          "201": {
+            "description": "Organization created",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/Organization"
+                }
+              }
+            }
+          },
+          "403": {
+            "description": "Access denied",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
             }
           },
+          "409": {
+            "description": "Conflict (slug already exists)",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/organizations/{org_slug}/access-report": {
+      "get": {
+        "tags": [
+          "access-reviews"
+        ],
+        "summary": "Get access report for a specific organization",
+        "description": "Returns a comprehensive access report for the specified organization including:\n- All org members with their roles and project access\n- All API keys scoped to the organization or its projects\n- Recent access grant history from audit logs\n- Summary statistics\n\nUse `format=csv` for CSV export suitable for auditors and spreadsheets.",
+        "operationId": "org_access_report",
+        "parameters": [
           {
-            "name": "project_slug",
+            "name": "org_slug",
             "in": "path",
-            "description": "Project slug",
+            "description": "Organization slug",
             "required": true,
             "schema": {
               "type": "string"
             }
           },
           {
-            "name": "lookback_days",
-            "in": "query",
-            "description": "Number of days of historical data to use (default: 30)",
-            "required": false,
-            "schema": {
-              "type": [
-                "integer",
-                "null"
-              ],
-              "format": "int32"
-            }
-          },
-          {
-            "name": "forecast_days",
+            "name": "format",
             "in": "query",
-            "description": "Number of days to forecast ahead (default: 7)",
+            "description": "Export format (json or csv)",
             "required": false,
             "schema": {
-              "type": [
-                "integer",
-                "null"
+              "oneOf": [
+                {
+                  "$ref": "#/components/schemas/ExportFormat"
+                }
               ],
-              "minimum": 0
+              "default": "json"
             }
           }
         ],
         "responses": {
           "200": {
-            "description": "Cost forecast",
+            "description": "Organization access report (JSON or CSV based on format parameter)",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/CostForecastResponse"
+                  "$ref": "#/components/schemas/OrgAccessReportResponse"
+                }
+              }
+            }
+          },
+          "403": {
+            "description": "Access denied",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
                 }
               }
             }
           },
           "404": {
-            "description": "Project not found",
+            "description": "Organization not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -4511,13 +4441,13 @@
         }
       }
     },
-    "/admin/v1/organizations/{org_slug}/prompts": {
+    "/admin/v1/organizations/{org_slug}/api-keys": {
       "get": {
         "tags": [
-          "prompts"
+          "api-keys"
         ],
-        "summary": "List prompts by organization",
-        "operationId": "prompt_list_by_org",
+        "summary": "List API keys by organization",
+        "operationId": "api_key_list_by_org",
         "parameters": [
           {
             "name": "org_slug",
@@ -4580,11 +4510,11 @@
         ],
         "responses": {
           "200": {
-            "description": "List of prompts",
+            "description": "List of API keys",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/PromptListResponse"
+                  "$ref": "#/components/schemas/ApiKeyListResponse"
                 }
               }
             }
@@ -4612,13 +4542,13 @@
         }
       }
     },
-    "/admin/v1/organizations/{org_slug}/rbac-policies": {
+    "/admin/v1/organizations/{org_slug}/dynamic-providers": {
       "get": {
         "tags": [
-          "rbac-policies"
+          "dynamic-providers"
         ],
-        "summary": "List RBAC policies for an organization",
-        "operationId": "org_rbac_policy_list",
+        "summary": "List dynamic providers by organization",
+        "operationId": "dynamic_provider_list_by_org",
         "parameters": [
           {
             "name": "org_slug",
@@ -4681,11 +4611,11 @@
         ],
         "responses": {
           "200": {
-            "description": "List of RBAC policies",
+            "description": "List of dynamic providers",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/OrgRbacPolicyListResponse"
+                  "$ref": "#/components/schemas/DynamicProviderListResponse"
                 }
               }
             }
@@ -4700,16 +4630,6 @@
               }
             }
           },
-          "403": {
-            "description": "Access denied",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
-            }
-          },
           "404": {
             "description": "Organization not found",
             "content": {
@@ -4721,13 +4641,15 @@
             }
           }
         }
-      },
-      "post": {
+      }
+    },
+    "/admin/v1/organizations/{org_slug}/members": {
+      "get": {
         "tags": [
-          "rbac-policies"
+          "users"
         ],
-        "summary": "Create a new RBAC policy for an organization",
-        "operationId": "org_rbac_policy_create",
+        "summary": "List organization members",
+        "operationId": "org_member_list",
         "parameters": [
           {
             "name": "org_slug",
@@ -4737,31 +4659,70 @@
             "schema": {
               "type": "string"
             }
-          }
-        ],
-        "requestBody": {
-          "content": {
-            "application/json": {
-              "schema": {
-                "$ref": "#/components/schemas/CreateOrgRbacPolicy"
-              }
+          },
+          {
+            "name": "limit",
+            "in": "query",
+            "description": "Maximum number of results to return",
+            "required": false,
+            "schema": {
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "int64"
             }
           },
-          "required": true
-        },
+          {
+            "name": "cursor",
+            "in": "query",
+            "description": "Cursor for keyset pagination. Encoded as base64 string.",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "direction",
+            "in": "query",
+            "description": "Pagination direction: \"forward\" (default) or \"backward\".",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "include_deleted",
+            "in": "query",
+            "description": "Include soft-deleted records in results",
+            "required": false,
+            "schema": {
+              "type": [
+                "boolean",
+                "null"
+              ]
+            }
+          }
+        ],
         "responses": {
-          "201": {
-            "description": "RBAC policy created",
+          "200": {
+            "description": "List of organization members",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/OrgRbacPolicy"
+                  "$ref": "#/components/schemas/UserListResponse"
                 }
               }
             }
           },
           "400": {
-            "description": "Invalid CEL expression",
+            "description": "Invalid cursor or direction",
             "content": {
               "application/json": {
                 "schema": {
@@ -4789,28 +4750,15 @@
                 }
               }
             }
-          },
-          "409": {
-            "description": "Policy with same name already exists",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
-            }
           }
         }
-      }
-    },
-    "/admin/v1/organizations/{org_slug}/rbac-policies/simulate": {
+      },
       "post": {
         "tags": [
-          "rbac-policies"
+          "users"
         ],
-        "summary": "Simulate policy evaluation for an organization",
-        "description": "Tests what decision would be made for a given subject and context.\nEvaluates both system policies (from config) and organization policies (from database),\nmatching the runtime authorization flow.\n\n## Evaluation Order\n\n1. Check if RBAC is disabled → return allow with `rbac_enabled: false`\n2. Evaluate system policies (from config file) first\n3. If a system policy matches → return that decision\n4. Evaluate organization policies (from database)\n5. If an org policy matches → return that decision\n6. No policy matched → apply configured `default_effect`",
-        "operationId": "org_rbac_policy_simulate",
+        "summary": "Add a member to an organization",
+        "operationId": "org_member_add",
         "parameters": [
           {
             "name": "org_slug",
@@ -4826,22 +4774,15 @@
           "content": {
             "application/json": {
               "schema": {
-                "$ref": "#/components/schemas/SimulatePolicyRequest"
+                "$ref": "#/components/schemas/AddMemberRequest"
               }
             }
           },
           "required": true
         },
         "responses": {
-          "200": {
-            "description": "Simulation result",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/SimulatePolicyResponse"
-                }
-              }
-            }
+          "201": {
+            "description": "Member added"
           },
           "403": {
             "description": "Access denied",
@@ -4854,7 +4795,7 @@
             }
           },
           "404": {
-            "description": "Organization not found",
+            "description": "Organization or user not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -4866,13 +4807,13 @@
         }
       }
     },
-    "/admin/v1/organizations/{org_slug}/rbac-policies/{policy_id}": {
-      "get": {
+    "/admin/v1/organizations/{org_slug}/members/{user_id}": {
+      "delete": {
         "tags": [
-          "rbac-policies"
+          "users"
         ],
-        "summary": "Get an RBAC policy by ID",
-        "operationId": "org_rbac_policy_get",
+        "summary": "Remove a member from an organization",
+        "operationId": "org_member_remove",
         "parameters": [
           {
             "name": "org_slug",
@@ -4884,9 +4825,9 @@
             }
           },
           {
-            "name": "policy_id",
+            "name": "user_id",
             "in": "path",
-            "description": "Policy ID",
+            "description": "User ID",
             "required": true,
             "schema": {
               "type": "string",
@@ -4896,14 +4837,7 @@
         ],
         "responses": {
           "200": {
-            "description": "RBAC policy found",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/OrgRbacPolicy"
-                }
-              }
-            }
+            "description": "Member removed"
           },
           "403": {
             "description": "Access denied",
@@ -4916,7 +4850,7 @@
             }
           },
           "404": {
-            "description": "Organization or policy not found",
+            "description": "Organization not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -4926,13 +4860,15 @@
             }
           }
         }
-      },
-      "delete": {
+      }
+    },
+    "/admin/v1/organizations/{org_slug}/model-pricing": {
+      "get": {
         "tags": [
-          "rbac-policies"
+          "model-pricing"
         ],
-        "summary": "Delete an RBAC policy",
-        "operationId": "org_rbac_policy_delete",
+        "summary": "List model pricing for an organization",
+        "operationId": "model_pricing_list_by_org",
         "parameters": [
           {
             "name": "org_slug",
@@ -4944,174 +4880,68 @@
             }
           },
           {
-            "name": "policy_id",
-            "in": "path",
-            "description": "Policy ID",
-            "required": true,
-            "schema": {
-              "type": "string",
-              "format": "uuid"
-            }
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "RBAC policy deleted"
-          },
-          "403": {
-            "description": "Access denied",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
-            }
-          },
-          "404": {
-            "description": "Organization or policy not found",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
-            }
-          }
-        }
-      },
-      "patch": {
-        "tags": [
-          "rbac-policies"
-        ],
-        "summary": "Update an RBAC policy",
-        "operationId": "org_rbac_policy_update",
-        "parameters": [
-          {
-            "name": "org_slug",
-            "in": "path",
-            "description": "Organization slug",
-            "required": true,
+            "name": "limit",
+            "in": "query",
+            "description": "Maximum number of results to return",
+            "required": false,
             "schema": {
-              "type": "string"
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "int64"
             }
           },
           {
-            "name": "policy_id",
-            "in": "path",
-            "description": "Policy ID",
-            "required": true,
+            "name": "cursor",
+            "in": "query",
+            "description": "Cursor for keyset pagination. Encoded as base64 string.",
+            "required": false,
             "schema": {
-              "type": "string",
-              "format": "uuid"
-            }
-          }
-        ],
-        "requestBody": {
-          "content": {
-            "application/json": {
-              "schema": {
-                "$ref": "#/components/schemas/UpdateOrgRbacPolicy"
-              }
-            }
-          },
-          "required": true
-        },
-        "responses": {
-          "200": {
-            "description": "RBAC policy updated",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/OrgRbacPolicy"
-                }
-              }
-            }
-          },
-          "400": {
-            "description": "Invalid CEL expression",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
-            }
-          },
-          "403": {
-            "description": "Access denied",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
+              "type": [
+                "string",
+                "null"
+              ]
             }
           },
-          "404": {
-            "description": "Organization or policy not found",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
-            }
-          }
-        }
-      }
-    },
-    "/admin/v1/organizations/{org_slug}/rbac-policies/{policy_id}/rollback": {
-      "post": {
-        "tags": [
-          "rbac-policies"
-        ],
-        "summary": "Rollback an RBAC policy to a previous version",
-        "operationId": "org_rbac_policy_rollback",
-        "parameters": [
           {
-            "name": "org_slug",
-            "in": "path",
-            "description": "Organization slug",
-            "required": true,
+            "name": "direction",
+            "in": "query",
+            "description": "Pagination direction: \"forward\" (default) or \"backward\".",
+            "required": false,
             "schema": {
-              "type": "string"
+              "type": [
+                "string",
+                "null"
+              ]
             }
           },
           {
-            "name": "policy_id",
-            "in": "path",
-            "description": "Policy ID",
-            "required": true,
+            "name": "include_deleted",
+            "in": "query",
+            "description": "Include soft-deleted records in results",
+            "required": false,
             "schema": {
-              "type": "string",
-              "format": "uuid"
+              "type": [
+                "boolean",
+                "null"
+              ]
             }
           }
         ],
-        "requestBody": {
-          "content": {
-            "application/json": {
-              "schema": {
-                "$ref": "#/components/schemas/RollbackOrgRbacPolicy"
-              }
-            }
-          },
-          "required": true
-        },
         "responses": {
           "200": {
-            "description": "Policy rolled back",
+            "description": "List of organization model pricing",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/OrgRbacPolicy"
+                  "$ref": "#/components/schemas/ModelPricingListResponse"
                 }
               }
             }
           },
-          "403": {
-            "description": "Access denied",
+          "400": {
+            "description": "Invalid cursor or direction",
             "content": {
               "application/json": {
                 "schema": {
@@ -5121,7 +4951,7 @@
             }
           },
           "404": {
-            "description": "Organization, policy, or version not found",
+            "description": "Organization not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -5133,13 +4963,13 @@
         }
       }
     },
-    "/admin/v1/organizations/{org_slug}/rbac-policies/{policy_id}/versions": {
+    "/admin/v1/organizations/{org_slug}/projects": {
       "get": {
         "tags": [
-          "rbac-policies"
+          "projects"
         ],
-        "summary": "List version history for an RBAC policy",
-        "operationId": "org_rbac_policy_list_versions",
+        "summary": "List projects in an organization",
+        "operationId": "project_list",
         "parameters": [
           {
             "name": "org_slug",
@@ -5150,16 +4980,6 @@
               "type": "string"
             }
           },
-          {
-            "name": "policy_id",
-            "in": "path",
-            "description": "Policy ID",
-            "required": true,
-            "schema": {
-              "type": "string",
-              "format": "uuid"
-            }
-          },
           {
             "name": "limit",
             "in": "query",
@@ -5212,11 +5032,11 @@
         ],
         "responses": {
           "200": {
-            "description": "List of policy versions",
+            "description": "List of projects",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/OrgRbacPolicyVersionListResponse"
+                  "$ref": "#/components/schemas/ProjectListResponse"
                 }
               }
             }
@@ -5242,7 +5062,7 @@
             }
           },
           "404": {
-            "description": "Organization or policy not found",
+            "description": "Organization not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -5252,15 +5072,13 @@
             }
           }
         }
-      }
-    },
-    "/admin/v1/organizations/{org_slug}/scim-config": {
-      "get": {
+      },
+      "post": {
         "tags": [
-          "scim"
+          "projects"
         ],
-        "summary": "Get the SCIM configuration for an organization",
-        "operationId": "org_scim_config_get",
+        "summary": "Create a project in an organization",
+        "operationId": "project_create",
         "parameters": [
           {
             "name": "org_slug",
@@ -5272,14 +5090,24 @@
             }
           }
         ],
-        "responses": {
-          "200": {
-            "description": "SCIM config found",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/OrgScimConfig"
-                }
+        "requestBody": {
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/CreateProject"
+              }
+            }
+          },
+          "required": true
+        },
+        "responses": {
+          "201": {
+            "description": "Project created",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/Project"
+                }
               }
             }
           },
@@ -5294,7 +5122,17 @@
             }
           },
           "404": {
-            "description": "Organization or SCIM config not found",
+            "description": "Organization not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "409": {
+            "description": "Conflict (slug already exists)",
             "content": {
               "application/json": {
                 "schema": {
@@ -5304,14 +5142,15 @@
             }
           }
         }
-      },
-      "post": {
+      }
+    },
+    "/admin/v1/organizations/{org_slug}/projects/{project_slug}": {
+      "get": {
         "tags": [
-          "scim"
+          "projects"
         ],
-        "summary": "Create a new SCIM configuration for an organization",
-        "description": "Each organization can have at most one SCIM configuration. Creating a config\nfor an organization that already has one will result in a 409 Conflict error.\n\nThe response includes the SCIM bearer token which is only shown once.\nStore it securely - it cannot be retrieved again.",
-        "operationId": "org_scim_config_create",
+        "summary": "Get a project by slug",
+        "operationId": "project_get",
         "parameters": [
           {
             "name": "org_slug",
@@ -5321,25 +5160,24 @@
             "schema": {
               "type": "string"
             }
+          },
+          {
+            "name": "project_slug",
+            "in": "path",
+            "description": "Project slug",
+            "required": true,
+            "schema": {
+              "type": "string"
+            }
           }
         ],
-        "requestBody": {
-          "content": {
-            "application/json": {
-              "schema": {
-                "$ref": "#/components/schemas/CreateOrgScimConfig"
-              }
-            }
-          },
-          "required": true
-        },
         "responses": {
-          "201": {
-            "description": "SCIM config created with bearer token",
+          "200": {
+            "description": "Project found",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/CreatedOrgScimConfig"
+                  "$ref": "#/components/schemas/Project"
                 }
               }
             }
@@ -5355,17 +5193,7 @@
             }
           },
           "404": {
-            "description": "Organization not found",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
-            }
-          },
-          "409": {
-            "description": "Organization already has a SCIM config",
+            "description": "Organization or project not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -5378,10 +5206,10 @@
       },
       "delete": {
         "tags": [
-          "scim"
+          "projects"
         ],
-        "summary": "Delete the SCIM configuration for an organization",
-        "operationId": "org_scim_config_delete",
+        "summary": "Delete a project",
+        "operationId": "project_delete",
         "parameters": [
           {
             "name": "org_slug",
@@ -5391,11 +5219,20 @@
             "schema": {
               "type": "string"
             }
+          },
+          {
+            "name": "project_slug",
+            "in": "path",
+            "description": "Project slug",
+            "required": true,
+            "schema": {
+              "type": "string"
+            }
           }
         ],
         "responses": {
           "200": {
-            "description": "SCIM config deleted"
+            "description": "Project deleted"
           },
           "403": {
             "description": "Access denied",
@@ -5408,7 +5245,7 @@
             }
           },
           "404": {
-            "description": "Organization or SCIM config not found",
+            "description": "Organization or project not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -5421,10 +5258,10 @@
       },
       "patch": {
         "tags": [
-          "scim"
+          "projects"
         ],
-        "summary": "Update the SCIM configuration for an organization",
-        "operationId": "org_scim_config_update",
+        "summary": "Update a project",
+        "operationId": "project_update",
         "parameters": [
           {
             "name": "org_slug",
@@ -5434,13 +5271,22 @@
             "schema": {
               "type": "string"
             }
+          },
+          {
+            "name": "project_slug",
+            "in": "path",
+            "description": "Project slug",
+            "required": true,
+            "schema": {
+              "type": "string"
+            }
           }
         ],
         "requestBody": {
           "content": {
             "application/json": {
               "schema": {
-                "$ref": "#/components/schemas/UpdateOrgScimConfig"
+                "$ref": "#/components/schemas/UpdateProject"
               }
             }
           },
@@ -5448,11 +5294,11 @@
         },
         "responses": {
           "200": {
-            "description": "SCIM config updated",
+            "description": "Project updated",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/OrgScimConfig"
+                  "$ref": "#/components/schemas/Project"
                 }
               }
             }
@@ -5468,7 +5314,7 @@
             }
           },
           "404": {
-            "description": "Organization or SCIM config not found",
+            "description": "Organization or project not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -5480,14 +5326,13 @@
         }
       }
     },
-    "/admin/v1/organizations/{org_slug}/scim-config/rotate-token": {
-      "post": {
+    "/admin/v1/organizations/{org_slug}/projects/{project_slug}/api-keys": {
+      "get": {
         "tags": [
-          "scim"
+          "api-keys"
         ],
-        "summary": "Rotate the SCIM bearer token for an organization",
-        "description": "Generates a new bearer token and invalidates the old one immediately.\nThe new token is returned only once - store it securely.",
-        "operationId": "org_scim_config_rotate_token",
+        "summary": "List API keys by project",
+        "operationId": "api_key_list_by_project",
         "parameters": [
           {
             "name": "org_slug",
@@ -5497,21 +5342,79 @@
             "schema": {
               "type": "string"
             }
+          },
+          {
+            "name": "project_slug",
+            "in": "path",
+            "description": "Project slug",
+            "required": true,
+            "schema": {
+              "type": "string"
+            }
+          },
+          {
+            "name": "limit",
+            "in": "query",
+            "description": "Maximum number of results to return",
+            "required": false,
+            "schema": {
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "int64"
+            }
+          },
+          {
+            "name": "cursor",
+            "in": "query",
+            "description": "Cursor for keyset pagination. Encoded as base64 string.",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "direction",
+            "in": "query",
+            "description": "Pagination direction: \"forward\" (default) or \"backward\".",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "include_deleted",
+            "in": "query",
+            "description": "Include soft-deleted records in results",
+            "required": false,
+            "schema": {
+              "type": [
+                "boolean",
+                "null"
+              ]
+            }
           }
         ],
         "responses": {
           "200": {
-            "description": "Token rotated successfully",
+            "description": "List of API keys",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/CreatedOrgScimConfig"
+                  "$ref": "#/components/schemas/ApiKeyListResponse"
                 }
               }
             }
           },
-          "403": {
-            "description": "Access denied",
+          "400": {
+            "description": "Invalid cursor or direction",
             "content": {
               "application/json": {
                 "schema": {
@@ -5521,7 +5424,7 @@
             }
           },
           "404": {
-            "description": "Organization or SCIM config not found",
+            "description": "Organization or project not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -5533,13 +5436,13 @@
         }
       }
     },
-    "/admin/v1/organizations/{org_slug}/service-accounts": {
+    "/admin/v1/organizations/{org_slug}/projects/{project_slug}/conversations": {
       "get": {
         "tags": [
-          "service_accounts"
+          "conversations"
         ],
-        "summary": "List service accounts in an organization",
-        "operationId": "service_account_list",
+        "summary": "List conversations by project",
+        "operationId": "conversation_list_by_project",
         "parameters": [
           {
             "name": "org_slug",
@@ -5550,6 +5453,15 @@
               "type": "string"
             }
           },
+          {
+            "name": "project_slug",
+            "in": "path",
+            "description": "Project slug",
+            "required": true,
+            "schema": {
+              "type": "string"
+            }
+          },
           {
             "name": "limit",
             "in": "query",
@@ -5602,11 +5514,11 @@
         ],
         "responses": {
           "200": {
-            "description": "List of service accounts",
+            "description": "List of conversations",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ServiceAccountListResponse"
+                  "$ref": "#/components/schemas/ConversationListResponse"
                 }
               }
             }
@@ -5621,18 +5533,8 @@
               }
             }
           },
-          "403": {
-            "description": "Access denied",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
-            }
-          },
           "404": {
-            "description": "Organization not found",
+            "description": "Organization or project not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -5642,13 +5544,15 @@
             }
           }
         }
-      },
-      "post": {
+      }
+    },
+    "/admin/v1/organizations/{org_slug}/projects/{project_slug}/dynamic-providers": {
+      "get": {
         "tags": [
-          "service_accounts"
+          "dynamic-providers"
         ],
-        "summary": "Create a service account in an organization",
-        "operationId": "service_account_create",
+        "summary": "List dynamic providers by project",
+        "operationId": "dynamic_provider_list_by_project",
         "parameters": [
           {
             "name": "org_slug",
@@ -5658,41 +5562,79 @@
             "schema": {
               "type": "string"
             }
-          }
-        ],
-        "requestBody": {
-          "content": {
-            "application/json": {
-              "schema": {
-                "$ref": "#/components/schemas/CreateServiceAccount"
-              }
-            }
           },
-          "required": true
-        },
-        "responses": {
-          "201": {
-            "description": "Service account created",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ServiceAccount"
-                }
-              }
+          {
+            "name": "project_slug",
+            "in": "path",
+            "description": "Project slug",
+            "required": true,
+            "schema": {
+              "type": "string"
             }
           },
-          "403": {
-            "description": "Access denied",
+          {
+            "name": "limit",
+            "in": "query",
+            "description": "Maximum number of results to return",
+            "required": false,
+            "schema": {
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "int64"
+            }
+          },
+          {
+            "name": "cursor",
+            "in": "query",
+            "description": "Cursor for keyset pagination. Encoded as base64 string.",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "direction",
+            "in": "query",
+            "description": "Pagination direction: \"forward\" (default) or \"backward\".",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "include_deleted",
+            "in": "query",
+            "description": "Include soft-deleted records in results",
+            "required": false,
+            "schema": {
+              "type": [
+                "boolean",
+                "null"
+              ]
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "List of dynamic providers",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "$ref": "#/components/schemas/DynamicProviderListResponse"
                 }
               }
             }
           },
-          "404": {
-            "description": "Organization not found",
+          "400": {
+            "description": "Invalid cursor or direction",
             "content": {
               "application/json": {
                 "schema": {
@@ -5701,8 +5643,8 @@
               }
             }
           },
-          "409": {
-            "description": "Conflict (slug already exists)",
+          "404": {
+            "description": "Organization or project not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -5714,13 +5656,13 @@
         }
       }
     },
-    "/admin/v1/organizations/{org_slug}/service-accounts/{sa_slug}": {
+    "/admin/v1/organizations/{org_slug}/projects/{project_slug}/members": {
       "get": {
         "tags": [
-          "service_accounts"
+          "users"
         ],
-        "summary": "Get a service account by slug",
-        "operationId": "service_account_get",
+        "summary": "List project members",
+        "operationId": "project_member_list",
         "parameters": [
           {
             "name": "org_slug",
@@ -5732,22 +5674,81 @@
             }
           },
           {
-            "name": "sa_slug",
+            "name": "project_slug",
             "in": "path",
-            "description": "Service account slug",
+            "description": "Project slug",
             "required": true,
             "schema": {
               "type": "string"
             }
+          },
+          {
+            "name": "limit",
+            "in": "query",
+            "description": "Maximum number of results to return",
+            "required": false,
+            "schema": {
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "int64"
+            }
+          },
+          {
+            "name": "cursor",
+            "in": "query",
+            "description": "Cursor for keyset pagination. Encoded as base64 string.",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "direction",
+            "in": "query",
+            "description": "Pagination direction: \"forward\" (default) or \"backward\".",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "include_deleted",
+            "in": "query",
+            "description": "Include soft-deleted records in results",
+            "required": false,
+            "schema": {
+              "type": [
+                "boolean",
+                "null"
+              ]
+            }
           }
         ],
         "responses": {
           "200": {
-            "description": "Service account found",
+            "description": "List of project members",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ServiceAccount"
+                  "$ref": "#/components/schemas/UserListResponse"
+                }
+              }
+            }
+          },
+          "400": {
+            "description": "Invalid cursor or direction",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
                 }
               }
             }
@@ -5763,7 +5764,7 @@
             }
           },
           "404": {
-            "description": "Organization or service account not found",
+            "description": "Organization or project not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -5774,12 +5775,12 @@
           }
         }
       },
-      "delete": {
+      "post": {
         "tags": [
-          "service_accounts"
+          "users"
         ],
-        "summary": "Delete a service account",
-        "operationId": "service_account_delete",
+        "summary": "Add a member to a project",
+        "operationId": "project_member_add",
         "parameters": [
           {
             "name": "org_slug",
@@ -5791,18 +5792,28 @@
             }
           },
           {
-            "name": "sa_slug",
+            "name": "project_slug",
             "in": "path",
-            "description": "Service account slug",
+            "description": "Project slug",
             "required": true,
             "schema": {
               "type": "string"
             }
           }
         ],
+        "requestBody": {
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/AddMemberRequest"
+              }
+            }
+          },
+          "required": true
+        },
         "responses": {
-          "200": {
-            "description": "Service account deleted"
+          "201": {
+            "description": "Member added"
           },
           "403": {
             "description": "Access denied",
@@ -5815,7 +5826,7 @@
             }
           },
           "404": {
-            "description": "Organization or service account not found",
+            "description": "Organization, project, or user not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -5825,13 +5836,15 @@
             }
           }
         }
-      },
-      "patch": {
+      }
+    },
+    "/admin/v1/organizations/{org_slug}/projects/{project_slug}/members/{user_id}": {
+      "delete": {
         "tags": [
-          "service_accounts"
+          "users"
         ],
-        "summary": "Update a service account",
-        "operationId": "service_account_update",
+        "summary": "Remove a member from a project",
+        "operationId": "project_member_remove",
         "parameters": [
           {
             "name": "org_slug",
@@ -5843,35 +5856,28 @@
             }
           },
           {
-            "name": "sa_slug",
+            "name": "project_slug",
             "in": "path",
-            "description": "Service account slug",
+            "description": "Project slug",
             "required": true,
             "schema": {
               "type": "string"
             }
+          },
+          {
+            "name": "user_id",
+            "in": "path",
+            "description": "User ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
           }
         ],
-        "requestBody": {
-          "content": {
-            "application/json": {
-              "schema": {
-                "$ref": "#/components/schemas/UpdateServiceAccount"
-              }
-            }
-          },
-          "required": true
-        },
         "responses": {
           "200": {
-            "description": "Service account updated",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ServiceAccount"
-                }
-              }
-            }
+            "description": "Member removed"
           },
           "403": {
             "description": "Access denied",
@@ -5884,7 +5890,7 @@
             }
           },
           "404": {
-            "description": "Organization or service account not found",
+            "description": "Organization or project not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -5896,13 +5902,13 @@
         }
       }
     },
-    "/admin/v1/organizations/{org_slug}/service-accounts/{sa_slug}/api-keys": {
+    "/admin/v1/organizations/{org_slug}/projects/{project_slug}/model-pricing": {
       "get": {
         "tags": [
-          "api-keys"
+          "model-pricing"
         ],
-        "summary": "List API keys by service account",
-        "operationId": "api_key_list_by_service_account",
+        "summary": "List model pricing for a project",
+        "operationId": "model_pricing_list_by_project",
         "parameters": [
           {
             "name": "org_slug",
@@ -5914,9 +5920,9 @@
             }
           },
           {
-            "name": "sa_slug",
+            "name": "project_slug",
             "in": "path",
-            "description": "Service account slug",
+            "description": "Project slug",
             "required": true,
             "schema": {
               "type": "string"
@@ -5974,11 +5980,11 @@
         ],
         "responses": {
           "200": {
-            "description": "List of API keys",
+            "description": "List of project model pricing",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ApiKeyListResponse"
+                  "$ref": "#/components/schemas/ModelPricingListResponse"
                 }
               }
             }
@@ -5993,18 +5999,8 @@
               }
             }
           },
-          "403": {
-            "description": "Access denied",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
-            }
-          },
-          "404": {
-            "description": "Organization or service account not found",
+          "404": {
+            "description": "Organization or project not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -6016,13 +6012,13 @@
         }
       }
     },
-    "/admin/v1/organizations/{org_slug}/sso-config": {
+    "/admin/v1/organizations/{org_slug}/projects/{project_slug}/templates": {
       "get": {
         "tags": [
-          "sso"
+          "templates"
         ],
-        "summary": "Get the SSO configuration for an organization",
-        "operationId": "org_sso_config_get",
+        "summary": "List templates by project",
+        "operationId": "template_list_by_project",
         "parameters": [
           {
             "name": "org_slug",
@@ -6032,21 +6028,79 @@
             "schema": {
               "type": "string"
             }
+          },
+          {
+            "name": "project_slug",
+            "in": "path",
+            "description": "Project slug",
+            "required": true,
+            "schema": {
+              "type": "string"
+            }
+          },
+          {
+            "name": "limit",
+            "in": "query",
+            "description": "Maximum number of results to return",
+            "required": false,
+            "schema": {
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "int64"
+            }
+          },
+          {
+            "name": "cursor",
+            "in": "query",
+            "description": "Cursor for keyset pagination. Encoded as base64 string.",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "direction",
+            "in": "query",
+            "description": "Pagination direction: \"forward\" (default) or \"backward\".",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "include_deleted",
+            "in": "query",
+            "description": "Include soft-deleted records in results",
+            "required": false,
+            "schema": {
+              "type": [
+                "boolean",
+                "null"
+              ]
+            }
           }
         ],
         "responses": {
           "200": {
-            "description": "SSO config found",
+            "description": "List of templates",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/OrgSsoConfig"
+                  "$ref": "#/components/schemas/TemplateListResponse"
                 }
               }
             }
           },
-          "403": {
-            "description": "Access denied",
+          "400": {
+            "description": "Invalid cursor or direction",
             "content": {
               "application/json": {
                 "schema": {
@@ -6056,7 +6110,7 @@
             }
           },
           "404": {
-            "description": "Organization or SSO config not found",
+            "description": "Organization or project not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -6066,14 +6120,15 @@
             }
           }
         }
-      },
-      "post": {
+      }
+    },
+    "/admin/v1/organizations/{org_slug}/projects/{project_slug}/usage": {
+      "get": {
         "tags": [
-          "sso"
+          "usage"
         ],
-        "summary": "Create a new SSO configuration for an organization",
-        "description": "Each organization can have at most one SSO configuration. Creating a config\nfor an organization that already has one will result in a 409 Conflict error.",
-        "operationId": "org_sso_config_create",
+        "summary": "Get usage summary for a project",
+        "operationId": "usage_get_project_summary",
         "parameters": [
           {
             "name": "org_slug",
@@ -6083,51 +6138,54 @@
             "schema": {
               "type": "string"
             }
-          }
-        ],
-        "requestBody": {
-          "content": {
-            "application/json": {
-              "schema": {
-                "$ref": "#/components/schemas/CreateOrgSsoConfig"
-              }
-            }
           },
-          "required": true
-        },
-        "responses": {
-          "201": {
-            "description": "SSO config created",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/OrgSsoConfig"
-                }
-              }
+          {
+            "name": "project_slug",
+            "in": "path",
+            "description": "Project slug",
+            "required": true,
+            "schema": {
+              "type": "string"
             }
           },
-          "403": {
-            "description": "Access denied",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
             }
           },
-          "404": {
-            "description": "Organization not found",
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Usage summary",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "$ref": "#/components/schemas/UsageSummaryResponse"
                 }
               }
             }
           },
-          "409": {
-            "description": "Organization already has an SSO config",
+          "404": {
+            "description": "Project not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -6137,13 +6195,15 @@
             }
           }
         }
-      },
-      "delete": {
+      }
+    },
+    "/admin/v1/organizations/{org_slug}/projects/{project_slug}/usage/by-date": {
+      "get": {
         "tags": [
-          "sso"
+          "usage"
         ],
-        "summary": "Delete the SSO configuration for an organization",
-        "operationId": "org_sso_config_delete",
+        "summary": "Get usage by date for a project",
+        "operationId": "usage_get_project_by_date",
         "parameters": [
           {
             "name": "org_slug",
@@ -6153,24 +6213,57 @@
             "schema": {
               "type": "string"
             }
+          },
+          {
+            "name": "project_slug",
+            "in": "path",
+            "description": "Project slug",
+            "required": true,
+            "schema": {
+              "type": "string"
+            }
+          },
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
           }
         ],
         "responses": {
           "200": {
-            "description": "SSO config deleted"
-          },
-          "403": {
-            "description": "Access denied",
+            "description": "Daily usage breakdown",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/DailySpendResponse"
+                  }
                 }
               }
             }
           },
           "404": {
-            "description": "Organization or SSO config not found",
+            "description": "Project not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -6180,13 +6273,15 @@
             }
           }
         }
-      },
-      "patch": {
+      }
+    },
+    "/admin/v1/organizations/{org_slug}/projects/{project_slug}/usage/by-date-model": {
+      "get": {
         "tags": [
-          "sso"
+          "usage"
         ],
-        "summary": "Update the SSO configuration for an organization",
-        "operationId": "org_sso_config_update",
+        "summary": "Get usage by date and model for a project",
+        "operationId": "usage_get_project_by_date_model",
         "parameters": [
           {
             "name": "org_slug",
@@ -6196,45 +6291,51 @@
             "schema": {
               "type": "string"
             }
-          }
-        ],
-        "requestBody": {
-          "content": {
-            "application/json": {
-              "schema": {
-                "$ref": "#/components/schemas/UpdateOrgSsoConfig"
-              }
-            }
           },
-          "required": true
-        },
-        "responses": {
-          "200": {
-            "description": "SSO config updated",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/OrgSsoConfig"
-                }
-              }
+          {
+            "name": "project_slug",
+            "in": "path",
+            "description": "Project slug",
+            "required": true,
+            "schema": {
+              "type": "string"
             }
           },
-          "403": {
-            "description": "Access denied",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
             }
           },
-          "404": {
-            "description": "Organization or SSO config not found",
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Daily usage breakdown by model",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/DailyModelSpendResponse"
+                  }
                 }
               }
             }
@@ -6242,13 +6343,13 @@
         }
       }
     },
-    "/admin/v1/organizations/{org_slug}/sso-config/domains": {
+    "/admin/v1/organizations/{org_slug}/projects/{project_slug}/usage/by-date-pricing-source": {
       "get": {
         "tags": [
-          "domain-verifications"
+          "usage"
         ],
-        "summary": "List all domain verifications for an organization's SSO config",
-        "operationId": "domain_verifications_list",
+        "summary": "Get usage by date and pricing source for a project",
+        "operationId": "usage_get_project_by_date_pricing_source",
         "parameters": [
           {
             "name": "org_slug",
@@ -6260,56 +6361,63 @@
             }
           },
           {
-            "name": "limit",
+            "name": "project_slug",
+            "in": "path",
+            "description": "Project slug",
+            "required": true,
+            "schema": {
+              "type": "string"
+            }
+          },
+          {
+            "name": "start_date",
             "in": "query",
-            "description": "Maximum number of items to return",
+            "description": "Start date (YYYY-MM-DD)",
             "required": false,
             "schema": {
-              "type": "integer",
-              "format": "int64"
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
             }
           }
         ],
         "responses": {
           "200": {
-            "description": "Domain verifications list",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ListDomainVerificationsResponse"
-                }
-              }
-            }
-          },
-          "403": {
-            "description": "Access denied",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
-            }
-          },
-          "404": {
-            "description": "Organization or SSO config not found",
+            "description": "Daily usage breakdown by pricing source",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/DailyPricingSourceSpendResponse"
+                  }
                 }
               }
             }
           }
         }
-      },
-      "post": {
+      }
+    },
+    "/admin/v1/organizations/{org_slug}/projects/{project_slug}/usage/by-date-provider": {
+      "get": {
         "tags": [
-          "domain-verifications"
+          "usage"
         ],
-        "summary": "Initiate domain verification for an organization's SSO config",
-        "description": "Creates a new domain verification record with a unique verification token.\nReturns the verification instructions with DNS record details.",
-        "operationId": "domain_verifications_create",
+        "summary": "Get usage by date and provider for a project",
+        "operationId": "usage_get_project_by_date_provider",
         "parameters": [
           {
             "name": "org_slug",
@@ -6319,65 +6427,51 @@
             "schema": {
               "type": "string"
             }
-          }
-        ],
-        "requestBody": {
-          "content": {
-            "application/json": {
-              "schema": {
-                "$ref": "#/components/schemas/CreateDomainVerification"
-              }
-            }
-          },
-          "required": true
-        },
-        "responses": {
-          "201": {
-            "description": "Domain verification initiated",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/DomainVerification"
-                }
-              }
-            }
           },
-          "400": {
-            "description": "Invalid domain or public domain blocked",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
+          {
+            "name": "project_slug",
+            "in": "path",
+            "description": "Project slug",
+            "required": true,
+            "schema": {
+              "type": "string"
             }
           },
-          "403": {
-            "description": "Access denied",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
             }
           },
-          "404": {
-            "description": "Organization or SSO config not found",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
             }
-          },
-          "409": {
-            "description": "Domain already being verified",
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Daily usage breakdown by provider",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/DailyProviderSpendResponse"
+                  }
                 }
               }
             }
@@ -6385,13 +6479,13 @@
         }
       }
     },
-    "/admin/v1/organizations/{org_slug}/sso-config/domains/{domain_id}": {
+    "/admin/v1/organizations/{org_slug}/projects/{project_slug}/usage/by-date-user": {
       "get": {
         "tags": [
-          "domain-verifications"
+          "usage"
         ],
-        "summary": "Get a specific domain verification by ID",
-        "operationId": "domain_verifications_get",
+        "summary": "Get usage by date and user for a project",
+        "operationId": "usage_get_project_by_date_user",
         "parameters": [
           {
             "name": "org_slug",
@@ -6403,39 +6497,55 @@
             }
           },
           {
-            "name": "domain_id",
+            "name": "project_slug",
             "in": "path",
-            "description": "Domain verification ID",
+            "description": "Project slug",
             "required": true,
             "schema": {
-              "type": "string",
-              "format": "uuid"
+              "type": "string"
+            }
+          },
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
             }
           }
         ],
         "responses": {
           "200": {
-            "description": "Domain verification found",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/DomainVerification"
-                }
-              }
-            }
-          },
-          "403": {
-            "description": "Access denied",
+            "description": "Daily usage breakdown by user",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/DailyUserSpendResponse"
+                  }
                 }
               }
             }
           },
           "404": {
-            "description": "Organization, SSO config, or domain verification not found",
+            "description": "Project not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -6445,13 +6555,15 @@
             }
           }
         }
-      },
-      "delete": {
+      }
+    },
+    "/admin/v1/organizations/{org_slug}/projects/{project_slug}/usage/by-model": {
+      "get": {
         "tags": [
-          "domain-verifications"
+          "usage"
         ],
-        "summary": "Delete a domain verification",
-        "operationId": "domain_verifications_delete",
+        "summary": "Get usage by model for a project",
+        "operationId": "usage_get_project_by_model",
         "parameters": [
           {
             "name": "org_slug",
@@ -6463,32 +6575,55 @@
             }
           },
           {
-            "name": "domain_id",
+            "name": "project_slug",
             "in": "path",
-            "description": "Domain verification ID",
+            "description": "Project slug",
             "required": true,
             "schema": {
-              "type": "string",
-              "format": "uuid"
+              "type": "string"
+            }
+          },
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
             }
           }
         ],
         "responses": {
           "200": {
-            "description": "Domain verification deleted"
-          },
-          "403": {
-            "description": "Access denied",
+            "description": "Usage breakdown by model",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/ModelSpendResponse"
+                  }
                 }
               }
             }
           },
           "404": {
-            "description": "Organization, SSO config, or domain verification not found",
+            "description": "Project not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -6500,13 +6635,13 @@
         }
       }
     },
-    "/admin/v1/organizations/{org_slug}/sso-config/domains/{domain_id}/instructions": {
+    "/admin/v1/organizations/{org_slug}/projects/{project_slug}/usage/by-pricing-source": {
       "get": {
         "tags": [
-          "domain-verifications"
+          "usage"
         ],
-        "summary": "Get verification instructions for a domain",
-        "operationId": "domain_verifications_get_instructions",
+        "summary": "Get usage by pricing source for a project",
+        "operationId": "usage_get_project_by_pricing_source",
         "parameters": [
           {
             "name": "org_slug",
@@ -6518,43 +6653,49 @@
             }
           },
           {
-            "name": "domain_id",
+            "name": "project_slug",
             "in": "path",
-            "description": "Domain verification ID",
+            "description": "Project slug",
             "required": true,
             "schema": {
-              "type": "string",
-              "format": "uuid"
+              "type": "string"
+            }
+          },
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
             }
           }
         ],
         "responses": {
           "200": {
-            "description": "Verification instructions",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/DomainVerificationInstructions"
-                }
-              }
-            }
-          },
-          "403": {
-            "description": "Access denied",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
-            }
-          },
-          "404": {
-            "description": "Organization, SSO config, or domain verification not found",
+            "description": "Usage breakdown by pricing source",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/PricingSourceSpendResponse"
+                  }
                 }
               }
             }
@@ -6562,14 +6703,13 @@
         }
       }
     },
-    "/admin/v1/organizations/{org_slug}/sso-config/domains/{domain_id}/verify": {
-      "post": {
+    "/admin/v1/organizations/{org_slug}/projects/{project_slug}/usage/by-provider": {
+      "get": {
         "tags": [
-          "domain-verifications"
+          "usage"
         ],
-        "summary": "Trigger DNS verification for a domain",
-        "description": "Performs a DNS TXT record lookup to verify domain ownership.",
-        "operationId": "domain_verifications_verify",
+        "summary": "Get usage by provider for a project",
+        "operationId": "usage_get_project_by_provider",
         "parameters": [
           {
             "name": "org_slug",
@@ -6581,39 +6721,55 @@
             }
           },
           {
-            "name": "domain_id",
+            "name": "project_slug",
             "in": "path",
-            "description": "Domain verification ID",
+            "description": "Project slug",
             "required": true,
             "schema": {
-              "type": "string",
-              "format": "uuid"
+              "type": "string"
+            }
+          },
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
             }
           }
         ],
         "responses": {
           "200": {
-            "description": "Verification attempt result",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/VerifyDomainResponse"
-                }
-              }
-            }
-          },
-          "403": {
-            "description": "Access denied",
+            "description": "Usage breakdown by provider",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/ProviderSpendResponse"
+                  }
                 }
               }
             }
           },
           "404": {
-            "description": "Organization, SSO config, or domain verification not found",
+            "description": "Project not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -6625,14 +6781,13 @@
         }
       }
     },
-    "/admin/v1/organizations/{org_slug}/sso-config/saml/parse-metadata": {
-      "post": {
+    "/admin/v1/organizations/{org_slug}/projects/{project_slug}/usage/by-user": {
+      "get": {
         "tags": [
-          "sso"
+          "usage"
         ],
-        "summary": "Parse SAML IdP metadata from a URL",
-        "description": "Fetches IdP metadata from the provided URL and extracts configuration fields.\nThis does NOT save the configuration - it returns the parsed data for admin review.\nUse the returned values to populate the SSO config fields.",
-        "operationId": "org_sso_config_parse_saml_metadata",
+        "summary": "Get usage by user for a project",
+        "operationId": "usage_get_project_by_user",
         "parameters": [
           {
             "name": "org_slug",
@@ -6642,51 +6797,57 @@
             "schema": {
               "type": "string"
             }
-          }
-        ],
-        "requestBody": {
-          "content": {
-            "application/json": {
-              "schema": {
-                "$ref": "#/components/schemas/ParseSamlMetadataRequest"
-              }
-            }
           },
-          "required": true
-        },
-        "responses": {
-          "200": {
-            "description": "Metadata parsed successfully",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ParsedSamlIdpConfig"
-                }
-              }
+          {
+            "name": "project_slug",
+            "in": "path",
+            "description": "Project slug",
+            "required": true,
+            "schema": {
+              "type": "string"
             }
           },
-          "400": {
-            "description": "Invalid metadata URL or failed to parse",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
             }
           },
-          "403": {
-            "description": "Access denied",
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Usage breakdown by user",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/UserSpendResponse"
+                  }
                 }
               }
             }
           },
           "404": {
-            "description": "Organization not found",
+            "description": "Project not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -6698,14 +6859,14 @@
         }
       }
     },
-    "/admin/v1/organizations/{org_slug}/sso-config/saml/sp-metadata": {
+    "/admin/v1/organizations/{org_slug}/projects/{project_slug}/usage/forecast": {
       "get": {
         "tags": [
-          "sso"
+          "usage"
         ],
-        "summary": "Get SP metadata for IdP configuration",
-        "description": "Returns Hadrian's Service Provider metadata XML that can be imported into\nthe IdP to configure the SAML integration automatically. The metadata includes\nthe SP entity ID, Assertion Consumer Service URL, and supported bindings.\n\nThis endpoint requires an existing SAML SSO configuration for the organization.",
-        "operationId": "org_sso_config_get_sp_metadata",
+        "summary": "Get cost forecast for a project",
+        "description": "Uses historical usage data across all API keys in the project to predict future spending.\nReturns average daily spend, confidence intervals, and time series forecasts.",
+        "operationId": "usage_get_project_forecast",
         "parameters": [
           {
             "name": "org_slug",
@@ -6715,27 +6876,56 @@
             "schema": {
               "type": "string"
             }
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "SP metadata XML",
-            "content": {
-              "application/samlmetadata+xml": {}
+          },
+          {
+            "name": "project_slug",
+            "in": "path",
+            "description": "Project slug",
+            "required": true,
+            "schema": {
+              "type": "string"
             }
           },
-          "403": {
-            "description": "Access denied",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
+          {
+            "name": "lookback_days",
+            "in": "query",
+            "description": "Number of days of historical data to use (default: 30)",
+            "required": false,
+            "schema": {
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "int32"
+            }
+          },
+          {
+            "name": "forecast_days",
+            "in": "query",
+            "description": "Number of days to forecast ahead (default: 7)",
+            "required": false,
+            "schema": {
+              "type": [
+                "integer",
+                "null"
+              ],
+              "minimum": 0
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Cost forecast",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/CostForecastResponse"
+                }
               }
             }
           },
           "404": {
-            "description": "Organization or SAML config not found",
+            "description": "Project not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -6747,13 +6937,13 @@
         }
       }
     },
-    "/admin/v1/organizations/{org_slug}/sso-group-mappings": {
+    "/admin/v1/organizations/{org_slug}/rbac-policies": {
       "get": {
         "tags": [
-          "sso"
+          "rbac-policies"
         ],
-        "summary": "List SSO group mappings for an organization",
-        "operationId": "sso_group_mapping_list",
+        "summary": "List RBAC policies for an organization",
+        "operationId": "org_rbac_policy_list",
         "parameters": [
           {
             "name": "org_slug",
@@ -6816,11 +7006,11 @@
         ],
         "responses": {
           "200": {
-            "description": "List of SSO group mappings",
+            "description": "List of RBAC policies",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/SsoGroupMappingListResponse"
+                  "$ref": "#/components/schemas/OrgRbacPolicyListResponse"
                 }
               }
             }
@@ -6859,10 +7049,10 @@
       },
       "post": {
         "tags": [
-          "sso"
+          "rbac-policies"
         ],
-        "summary": "Create a new SSO group mapping",
-        "operationId": "sso_group_mapping_create",
+        "summary": "Create a new RBAC policy for an organization",
+        "operationId": "org_rbac_policy_create",
         "parameters": [
           {
             "name": "org_slug",
@@ -6878,7 +7068,7 @@
           "content": {
             "application/json": {
               "schema": {
-                "$ref": "#/components/schemas/CreateSsoGroupMapping"
+                "$ref": "#/components/schemas/CreateOrgRbacPolicy"
               }
             }
           },
@@ -6886,17 +7076,17 @@
         },
         "responses": {
           "201": {
-            "description": "SSO group mapping created",
+            "description": "RBAC policy created",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/SsoGroupMapping"
+                  "$ref": "#/components/schemas/OrgRbacPolicy"
                 }
               }
             }
           },
-          "403": {
-            "description": "Access denied",
+          "400": {
+            "description": "Invalid CEL expression",
             "content": {
               "application/json": {
                 "schema": {
@@ -6905,8 +7095,8 @@
               }
             }
           },
-          "404": {
-            "description": "Organization not found",
+          "403": {
+            "description": "Access denied",
             "content": {
               "application/json": {
                 "schema": {
@@ -6914,59 +7104,9 @@
                 }
               }
             }
-          }
-        }
-      }
-    },
-    "/admin/v1/organizations/{org_slug}/sso-group-mappings/export": {
-      "get": {
-        "tags": [
-          "sso"
-        ],
-        "summary": "Export SSO group mappings",
-        "description": "Exports all SSO group mappings for an organization in JSON or CSV format.\nUseful for backup, migration, or bulk editing in a spreadsheet.",
-        "operationId": "sso_group_mapping_export",
-        "parameters": [
-          {
-            "name": "org_slug",
-            "in": "path",
-            "description": "Organization slug",
-            "required": true,
-            "schema": {
-              "type": "string"
-            }
-          },
-          {
-            "name": "format",
-            "in": "query",
-            "description": "Export format (json or csv, defaults to json)",
-            "required": false,
-            "schema": {
-              "$ref": "#/components/schemas/ExportFormat"
-            }
-          },
-          {
-            "name": "sso_connection_name",
-            "in": "query",
-            "description": "Filter by SSO connection name (optional)",
-            "required": false,
-            "schema": {
-              "type": [
-                "string",
-                "null"
-              ]
-            }
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "Export of SSO group mappings as CSV",
-            "content": {
-              "text/csv": {}
-            }
           },
-          "403": {
-            "description": "Access denied",
+          "404": {
+            "description": "Organization not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -6975,8 +7115,8 @@
               }
             }
           },
-          "404": {
-            "description": "Organization not found",
+          "409": {
+            "description": "Policy with same name already exists",
             "content": {
               "application/json": {
                 "schema": {
@@ -6988,14 +7128,14 @@
         }
       }
     },
-    "/admin/v1/organizations/{org_slug}/sso-group-mappings/import": {
+    "/admin/v1/organizations/{org_slug}/rbac-policies/simulate": {
       "post": {
         "tags": [
-          "sso"
+          "rbac-policies"
         ],
-        "summary": "Import SSO group mappings",
-        "description": "Bulk import SSO group mappings from a JSON payload. Useful for migrating\nmappings between environments or restoring from a backup.",
-        "operationId": "sso_group_mapping_import",
+        "summary": "Simulate policy evaluation for an organization",
+        "description": "Tests what decision would be made for a given subject and context.\nEvaluates both system policies (from config) and organization policies (from database),\nmatching the runtime authorization flow.\n\n## Evaluation Order\n\n1. Check if RBAC is disabled → return allow with `rbac_enabled: false`\n2. Evaluate system policies (from config file) first\n3. If a system policy matches → return that decision\n4. Evaluate organization policies (from database)\n5. If an org policy matches → return that decision\n6. No policy matched → apply configured `default_effect`",
+        "operationId": "org_rbac_policy_simulate",
         "parameters": [
           {
             "name": "org_slug",
@@ -7011,7 +7151,7 @@
           "content": {
             "application/json": {
               "schema": {
-                "$ref": "#/components/schemas/ImportRequest"
+                "$ref": "#/components/schemas/SimulatePolicyRequest"
               }
             }
           },
@@ -7019,21 +7159,11 @@
         },
         "responses": {
           "200": {
-            "description": "Import completed",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ImportResponse"
-                }
-              }
-            }
-          },
-          "400": {
-            "description": "Invalid request or conflict error",
+            "description": "Simulation result",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "$ref": "#/components/schemas/SimulatePolicyResponse"
                 }
               }
             }
@@ -7061,14 +7191,13 @@
         }
       }
     },
-    "/admin/v1/organizations/{org_slug}/sso-group-mappings/test": {
-      "post": {
+    "/admin/v1/organizations/{org_slug}/rbac-policies/{policy_id}": {
+      "get": {
         "tags": [
-          "sso"
+          "rbac-policies"
         ],
-        "summary": "Test SSO group mapping resolution",
-        "description": "Given a list of IdP group names, returns what teams/roles a user with those\ngroups would be resolved to. This is useful for debugging and verifying\nmapping configuration.",
-        "operationId": "sso_group_mapping_test",
+        "summary": "Get an RBAC policy by ID",
+        "operationId": "org_rbac_policy_get",
         "parameters": [
           {
             "name": "org_slug",
@@ -7078,35 +7207,25 @@
             "schema": {
               "type": "string"
             }
+          },
+          {
+            "name": "policy_id",
+            "in": "path",
+            "description": "Policy ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
           }
         ],
-        "requestBody": {
-          "content": {
-            "application/json": {
-              "schema": {
-                "$ref": "#/components/schemas/TestMappingRequest"
-              }
-            }
-          },
-          "required": true
-        },
         "responses": {
           "200": {
-            "description": "Mapping test results",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/TestMappingResponse"
-                }
-              }
-            }
-          },
-          "400": {
-            "description": "Invalid request",
+            "description": "RBAC policy found",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "$ref": "#/components/schemas/OrgRbacPolicy"
                 }
               }
             }
@@ -7122,7 +7241,7 @@
             }
           },
           "404": {
-            "description": "Organization not found",
+            "description": "Organization or policy not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -7132,15 +7251,13 @@
             }
           }
         }
-      }
-    },
-    "/admin/v1/organizations/{org_slug}/sso-group-mappings/{mapping_id}": {
-      "get": {
+      },
+      "delete": {
         "tags": [
-          "sso"
+          "rbac-policies"
         ],
-        "summary": "Get an SSO group mapping by ID",
-        "operationId": "sso_group_mapping_get",
+        "summary": "Delete an RBAC policy",
+        "operationId": "org_rbac_policy_delete",
         "parameters": [
           {
             "name": "org_slug",
@@ -7152,9 +7269,9 @@
             }
           },
           {
-            "name": "mapping_id",
+            "name": "policy_id",
             "in": "path",
-            "description": "Mapping ID",
+            "description": "Policy ID",
             "required": true,
             "schema": {
               "type": "string",
@@ -7164,14 +7281,7 @@
         ],
         "responses": {
           "200": {
-            "description": "SSO group mapping found",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/SsoGroupMapping"
-                }
-              }
-            }
+            "description": "RBAC policy deleted"
           },
           "403": {
             "description": "Access denied",
@@ -7184,7 +7294,7 @@
             }
           },
           "404": {
-            "description": "Organization or mapping not found",
+            "description": "Organization or policy not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -7195,12 +7305,12 @@
           }
         }
       },
-      "delete": {
+      "patch": {
         "tags": [
-          "sso"
+          "rbac-policies"
         ],
-        "summary": "Delete an SSO group mapping",
-        "operationId": "sso_group_mapping_delete",
+        "summary": "Update an RBAC policy",
+        "operationId": "org_rbac_policy_update",
         "parameters": [
           {
             "name": "org_slug",
@@ -7212,9 +7322,9 @@
             }
           },
           {
-            "name": "mapping_id",
+            "name": "policy_id",
             "in": "path",
-            "description": "Mapping ID",
+            "description": "Policy ID",
             "required": true,
             "schema": {
               "type": "string",
@@ -7222,22 +7332,49 @@
             }
           }
         ],
+        "requestBody": {
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/UpdateOrgRbacPolicy"
+              }
+            }
+          },
+          "required": true
+        },
         "responses": {
           "200": {
-            "description": "SSO group mapping deleted"
-          },
-          "403": {
-            "description": "Access denied",
+            "description": "RBAC policy updated",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "$ref": "#/components/schemas/OrgRbacPolicy"
                 }
               }
             }
           },
-          "404": {
-            "description": "Organization or mapping not found",
+          "400": {
+            "description": "Invalid CEL expression",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "403": {
+            "description": "Access denied",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "404": {
+            "description": "Organization or policy not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -7247,13 +7384,15 @@
             }
           }
         }
-      },
-      "patch": {
+      }
+    },
+    "/admin/v1/organizations/{org_slug}/rbac-policies/{policy_id}/rollback": {
+      "post": {
         "tags": [
-          "sso"
+          "rbac-policies"
         ],
-        "summary": "Update an SSO group mapping",
-        "operationId": "sso_group_mapping_update",
+        "summary": "Rollback an RBAC policy to a previous version",
+        "operationId": "org_rbac_policy_rollback",
         "parameters": [
           {
             "name": "org_slug",
@@ -7265,9 +7404,9 @@
             }
           },
           {
-            "name": "mapping_id",
+            "name": "policy_id",
             "in": "path",
-            "description": "Mapping ID",
+            "description": "Policy ID",
             "required": true,
             "schema": {
               "type": "string",
@@ -7279,7 +7418,7 @@
           "content": {
             "application/json": {
               "schema": {
-                "$ref": "#/components/schemas/UpdateSsoGroupMapping"
+                "$ref": "#/components/schemas/RollbackOrgRbacPolicy"
               }
             }
           },
@@ -7287,11 +7426,11 @@
         },
         "responses": {
           "200": {
-            "description": "SSO group mapping updated",
+            "description": "Policy rolled back",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/SsoGroupMapping"
+                  "$ref": "#/components/schemas/OrgRbacPolicy"
                 }
               }
             }
@@ -7307,7 +7446,7 @@
             }
           },
           "404": {
-            "description": "Organization or mapping not found",
+            "description": "Organization, policy, or version not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -7319,13 +7458,13 @@
         }
       }
     },
-    "/admin/v1/organizations/{org_slug}/teams": {
+    "/admin/v1/organizations/{org_slug}/rbac-policies/{policy_id}/versions": {
       "get": {
         "tags": [
-          "teams"
+          "rbac-policies"
         ],
-        "summary": "List teams in an organization",
-        "operationId": "team_list",
+        "summary": "List version history for an RBAC policy",
+        "operationId": "org_rbac_policy_list_versions",
         "parameters": [
           {
             "name": "org_slug",
@@ -7336,6 +7475,16 @@
               "type": "string"
             }
           },
+          {
+            "name": "policy_id",
+            "in": "path",
+            "description": "Policy ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          },
           {
             "name": "limit",
             "in": "query",
@@ -7388,11 +7537,11 @@
         ],
         "responses": {
           "200": {
-            "description": "List of teams",
+            "description": "List of policy versions",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/TeamListResponse"
+                  "$ref": "#/components/schemas/OrgRbacPolicyVersionListResponse"
                 }
               }
             }
@@ -7418,7 +7567,59 @@
             }
           },
           "404": {
-            "description": "Organization not found",
+            "description": "Organization or policy not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/organizations/{org_slug}/scim-config": {
+      "get": {
+        "tags": [
+          "scim"
+        ],
+        "summary": "Get the SCIM configuration for an organization",
+        "operationId": "org_scim_config_get",
+        "parameters": [
+          {
+            "name": "org_slug",
+            "in": "path",
+            "description": "Organization slug",
+            "required": true,
+            "schema": {
+              "type": "string"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "SCIM config found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/OrgScimConfig"
+                }
+              }
+            }
+          },
+          "403": {
+            "description": "Access denied",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "404": {
+            "description": "Organization or SCIM config not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -7431,10 +7632,11 @@
       },
       "post": {
         "tags": [
-          "teams"
+          "scim"
         ],
-        "summary": "Create a team in an organization",
-        "operationId": "team_create",
+        "summary": "Create a new SCIM configuration for an organization",
+        "description": "Each organization can have at most one SCIM configuration. Creating a config\nfor an organization that already has one will result in a 409 Conflict error.\n\nThe response includes the SCIM bearer token which is only shown once.\nStore it securely - it cannot be retrieved again.",
+        "operationId": "org_scim_config_create",
         "parameters": [
           {
             "name": "org_slug",
@@ -7450,7 +7652,7 @@
           "content": {
             "application/json": {
               "schema": {
-                "$ref": "#/components/schemas/CreateTeam"
+                "$ref": "#/components/schemas/CreateOrgScimConfig"
               }
             }
           },
@@ -7458,11 +7660,11 @@
         },
         "responses": {
           "201": {
-            "description": "Team created",
+            "description": "SCIM config created with bearer token",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/Team"
+                  "$ref": "#/components/schemas/CreatedOrgScimConfig"
                 }
               }
             }
@@ -7488,7 +7690,7 @@
             }
           },
           "409": {
-            "description": "Conflict (slug already exists)",
+            "description": "Organization already has a SCIM config",
             "content": {
               "application/json": {
                 "schema": {
@@ -7498,15 +7700,13 @@
             }
           }
         }
-      }
-    },
-    "/admin/v1/organizations/{org_slug}/teams/{team_slug}": {
-      "get": {
+      },
+      "delete": {
         "tags": [
-          "teams"
+          "scim"
         ],
-        "summary": "Get a team by slug",
-        "operationId": "team_get",
+        "summary": "Delete the SCIM configuration for an organization",
+        "operationId": "org_scim_config_delete",
         "parameters": [
           {
             "name": "org_slug",
@@ -7516,27 +7716,11 @@
             "schema": {
               "type": "string"
             }
-          },
-          {
-            "name": "team_slug",
-            "in": "path",
-            "description": "Team slug",
-            "required": true,
-            "schema": {
-              "type": "string"
-            }
           }
         ],
         "responses": {
           "200": {
-            "description": "Team found",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/Team"
-                }
-              }
-            }
+            "description": "SCIM config deleted"
           },
           "403": {
             "description": "Access denied",
@@ -7549,7 +7733,7 @@
             }
           },
           "404": {
-            "description": "Organization or team not found",
+            "description": "Organization or SCIM config not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -7560,12 +7744,12 @@
           }
         }
       },
-      "delete": {
+      "patch": {
         "tags": [
-          "teams"
+          "scim"
         ],
-        "summary": "Delete a team",
-        "operationId": "team_delete",
+        "summary": "Update the SCIM configuration for an organization",
+        "operationId": "org_scim_config_update",
         "parameters": [
           {
             "name": "org_slug",
@@ -7575,20 +7759,28 @@
             "schema": {
               "type": "string"
             }
-          },
-          {
-            "name": "team_slug",
-            "in": "path",
-            "description": "Team slug",
-            "required": true,
-            "schema": {
-              "type": "string"
-            }
           }
         ],
+        "requestBody": {
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/UpdateOrgScimConfig"
+              }
+            }
+          },
+          "required": true
+        },
         "responses": {
           "200": {
-            "description": "Team deleted"
+            "description": "SCIM config updated",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/OrgScimConfig"
+                }
+              }
+            }
           },
           "403": {
             "description": "Access denied",
@@ -7601,7 +7793,7 @@
             }
           },
           "404": {
-            "description": "Organization or team not found",
+            "description": "Organization or SCIM config not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -7611,13 +7803,16 @@
             }
           }
         }
-      },
-      "patch": {
+      }
+    },
+    "/admin/v1/organizations/{org_slug}/scim-config/rotate-token": {
+      "post": {
         "tags": [
-          "teams"
+          "scim"
         ],
-        "summary": "Update a team",
-        "operationId": "team_update",
+        "summary": "Rotate the SCIM bearer token for an organization",
+        "description": "Generates a new bearer token and invalidates the old one immediately.\nThe new token is returned only once - store it securely.",
+        "operationId": "org_scim_config_rotate_token",
         "parameters": [
           {
             "name": "org_slug",
@@ -7627,34 +7822,15 @@
             "schema": {
               "type": "string"
             }
-          },
-          {
-            "name": "team_slug",
-            "in": "path",
-            "description": "Team slug",
-            "required": true,
-            "schema": {
-              "type": "string"
-            }
           }
         ],
-        "requestBody": {
-          "content": {
-            "application/json": {
-              "schema": {
-                "$ref": "#/components/schemas/UpdateTeam"
-              }
-            }
-          },
-          "required": true
-        },
         "responses": {
           "200": {
-            "description": "Team updated",
+            "description": "Token rotated successfully",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/Team"
+                  "$ref": "#/components/schemas/CreatedOrgScimConfig"
                 }
               }
             }
@@ -7670,7 +7846,7 @@
             }
           },
           "404": {
-            "description": "Organization or team not found",
+            "description": "Organization or SCIM config not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -7682,13 +7858,13 @@
         }
       }
     },
-    "/admin/v1/organizations/{org_slug}/teams/{team_slug}/members": {
+    "/admin/v1/organizations/{org_slug}/service-accounts": {
       "get": {
         "tags": [
-          "teams"
+          "service_accounts"
         ],
-        "summary": "List team members",
-        "operationId": "team_member_list",
+        "summary": "List service accounts in an organization",
+        "operationId": "service_account_list",
         "parameters": [
           {
             "name": "org_slug",
@@ -7699,15 +7875,6 @@
               "type": "string"
             }
           },
-          {
-            "name": "team_slug",
-            "in": "path",
-            "description": "Team slug",
-            "required": true,
-            "schema": {
-              "type": "string"
-            }
-          },
           {
             "name": "limit",
             "in": "query",
@@ -7760,11 +7927,11 @@
         ],
         "responses": {
           "200": {
-            "description": "List of team members",
+            "description": "List of service accounts",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/TeamMemberListResponse"
+                  "$ref": "#/components/schemas/ServiceAccountListResponse"
                 }
               }
             }
@@ -7790,7 +7957,7 @@
             }
           },
           "404": {
-            "description": "Organization or team not found",
+            "description": "Organization not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -7803,10 +7970,10 @@
       },
       "post": {
         "tags": [
-          "teams"
+          "service_accounts"
         ],
-        "summary": "Add a member to a team",
-        "operationId": "team_member_add",
+        "summary": "Create a service account in an organization",
+        "operationId": "service_account_create",
         "parameters": [
           {
             "name": "org_slug",
@@ -7816,22 +7983,13 @@
             "schema": {
               "type": "string"
             }
-          },
-          {
-            "name": "team_slug",
-            "in": "path",
-            "description": "Team slug",
-            "required": true,
-            "schema": {
-              "type": "string"
-            }
           }
         ],
         "requestBody": {
           "content": {
             "application/json": {
               "schema": {
-                "$ref": "#/components/schemas/AddTeamMember"
+                "$ref": "#/components/schemas/CreateServiceAccount"
               }
             }
           },
@@ -7839,11 +7997,11 @@
         },
         "responses": {
           "201": {
-            "description": "Member added",
+            "description": "Service account created",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/TeamMember"
+                  "$ref": "#/components/schemas/ServiceAccount"
                 }
               }
             }
@@ -7859,7 +8017,7 @@
             }
           },
           "404": {
-            "description": "Organization, team, or user not found",
+            "description": "Organization not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -7869,7 +8027,7 @@
             }
           },
           "409": {
-            "description": "User is already a member",
+            "description": "Conflict (slug already exists)",
             "content": {
               "application/json": {
                 "schema": {
@@ -7881,13 +8039,13 @@
         }
       }
     },
-    "/admin/v1/organizations/{org_slug}/teams/{team_slug}/members/{user_id}": {
-      "delete": {
+    "/admin/v1/organizations/{org_slug}/service-accounts/{sa_slug}": {
+      "get": {
         "tags": [
-          "teams"
+          "service_accounts"
         ],
-        "summary": "Remove a member from a team",
-        "operationId": "team_member_remove",
+        "summary": "Get a service account by slug",
+        "operationId": "service_account_get",
         "parameters": [
           {
             "name": "org_slug",
@@ -7899,28 +8057,77 @@
             }
           },
           {
-            "name": "team_slug",
+            "name": "sa_slug",
             "in": "path",
-            "description": "Team slug",
+            "description": "Service account slug",
+            "required": true,
+            "schema": {
+              "type": "string"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Service account found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ServiceAccount"
+                }
+              }
+            }
+          },
+          "403": {
+            "description": "Access denied",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "404": {
+            "description": "Organization or service account not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        }
+      },
+      "delete": {
+        "tags": [
+          "service_accounts"
+        ],
+        "summary": "Delete a service account",
+        "operationId": "service_account_delete",
+        "parameters": [
+          {
+            "name": "org_slug",
+            "in": "path",
+            "description": "Organization slug",
             "required": true,
             "schema": {
               "type": "string"
             }
           },
           {
-            "name": "user_id",
+            "name": "sa_slug",
             "in": "path",
-            "description": "User ID",
+            "description": "Service account slug",
             "required": true,
             "schema": {
-              "type": "string",
-              "format": "uuid"
+              "type": "string"
             }
           }
         ],
         "responses": {
           "200": {
-            "description": "Member removed"
+            "description": "Service account deleted"
           },
           "403": {
             "description": "Access denied",
@@ -7933,7 +8140,7 @@
             }
           },
           "404": {
-            "description": "Organization, team, or membership not found",
+            "description": "Organization or service account not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -7946,10 +8153,10 @@
       },
       "patch": {
         "tags": [
-          "teams"
+          "service_accounts"
         ],
-        "summary": "Update a team member's role",
-        "operationId": "team_member_update",
+        "summary": "Update a service account",
+        "operationId": "service_account_update",
         "parameters": [
           {
             "name": "org_slug",
@@ -7961,30 +8168,20 @@
             }
           },
           {
-            "name": "team_slug",
+            "name": "sa_slug",
             "in": "path",
-            "description": "Team slug",
+            "description": "Service account slug",
             "required": true,
             "schema": {
               "type": "string"
             }
-          },
-          {
-            "name": "user_id",
-            "in": "path",
-            "description": "User ID",
-            "required": true,
-            "schema": {
-              "type": "string",
-              "format": "uuid"
-            }
           }
         ],
         "requestBody": {
           "content": {
             "application/json": {
               "schema": {
-                "$ref": "#/components/schemas/UpdateTeamMember"
+                "$ref": "#/components/schemas/UpdateServiceAccount"
               }
             }
           },
@@ -7992,11 +8189,11 @@
         },
         "responses": {
           "200": {
-            "description": "Member role updated",
+            "description": "Service account updated",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/TeamMember"
+                  "$ref": "#/components/schemas/ServiceAccount"
                 }
               }
             }
@@ -8012,7 +8209,7 @@
             }
           },
           "404": {
-            "description": "Organization, team, or membership not found",
+            "description": "Organization or service account not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -8024,13 +8221,13 @@
         }
       }
     },
-    "/admin/v1/organizations/{org_slug}/teams/{team_slug}/prompts": {
+    "/admin/v1/organizations/{org_slug}/service-accounts/{sa_slug}/api-keys": {
       "get": {
         "tags": [
-          "prompts"
+          "api-keys"
         ],
-        "summary": "List prompts by team",
-        "operationId": "prompt_list_by_team",
+        "summary": "List API keys by service account",
+        "operationId": "api_key_list_by_service_account",
         "parameters": [
           {
             "name": "org_slug",
@@ -8042,9 +8239,9 @@
             }
           },
           {
-            "name": "team_slug",
+            "name": "sa_slug",
             "in": "path",
-            "description": "Team slug",
+            "description": "Service account slug",
             "required": true,
             "schema": {
               "type": "string"
@@ -8102,11 +8299,11 @@
         ],
         "responses": {
           "200": {
-            "description": "List of prompts",
+            "description": "List of API keys",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/PromptListResponse"
+                  "$ref": "#/components/schemas/ApiKeyListResponse"
                 }
               }
             }
@@ -8121,8 +8318,18 @@
               }
             }
           },
+          "403": {
+            "description": "Access denied",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
           "404": {
-            "description": "Organization or team not found",
+            "description": "Organization or service account not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -8134,16 +8341,16 @@
         }
       }
     },
-    "/admin/v1/organizations/{slug}": {
+    "/admin/v1/organizations/{org_slug}/sso-config": {
       "get": {
         "tags": [
-          "organizations"
+          "sso"
         ],
-        "summary": "Get an organization by slug",
-        "operationId": "organization_get",
+        "summary": "Get the SSO configuration for an organization",
+        "operationId": "org_sso_config_get",
         "parameters": [
           {
-            "name": "slug",
+            "name": "org_slug",
             "in": "path",
             "description": "Organization slug",
             "required": true,
@@ -8154,11 +8361,11 @@
         ],
         "responses": {
           "200": {
-            "description": "Organization found",
+            "description": "SSO config found",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/Organization"
+                  "$ref": "#/components/schemas/OrgSsoConfig"
                 }
               }
             }
@@ -8174,7 +8381,7 @@
             }
           },
           "404": {
-            "description": "Organization not found",
+            "description": "Organization or SSO config not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -8185,15 +8392,16 @@
           }
         }
       },
-      "delete": {
+      "post": {
         "tags": [
-          "organizations"
+          "sso"
         ],
-        "summary": "Delete an organization",
-        "operationId": "organization_delete",
+        "summary": "Create a new SSO configuration for an organization",
+        "description": "Each organization can have at most one SSO configuration. Creating a config\nfor an organization that already has one will result in a 409 Conflict error.",
+        "operationId": "org_sso_config_create",
         "parameters": [
           {
-            "name": "slug",
+            "name": "org_slug",
             "in": "path",
             "description": "Organization slug",
             "required": true,
@@ -8202,9 +8410,26 @@
             }
           }
         ],
+        "requestBody": {
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/CreateOrgSsoConfig"
+              }
+            }
+          },
+          "required": true
+        },
         "responses": {
-          "200": {
-            "description": "Organization deleted"
+          "201": {
+            "description": "SSO config created",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/OrgSsoConfig"
+                }
+              }
+            }
           },
           "403": {
             "description": "Access denied",
@@ -8225,18 +8450,28 @@
                 }
               }
             }
+          },
+          "409": {
+            "description": "Organization already has an SSO config",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
           }
         }
       },
-      "patch": {
+      "delete": {
         "tags": [
-          "organizations"
+          "sso"
         ],
-        "summary": "Update an organization",
-        "operationId": "organization_update",
+        "summary": "Delete the SSO configuration for an organization",
+        "operationId": "org_sso_config_delete",
         "parameters": [
           {
-            "name": "slug",
+            "name": "org_slug",
             "in": "path",
             "description": "Organization slug",
             "required": true,
@@ -8245,26 +8480,9 @@
             }
           }
         ],
-        "requestBody": {
-          "content": {
-            "application/json": {
-              "schema": {
-                "$ref": "#/components/schemas/UpdateOrganization"
-              }
-            }
-          },
-          "required": true
-        },
         "responses": {
           "200": {
-            "description": "Organization updated",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/Organization"
-                }
-              }
-            }
+            "description": "SSO config deleted"
           },
           "403": {
             "description": "Access denied",
@@ -8277,7 +8495,7 @@
             }
           },
           "404": {
-            "description": "Organization not found",
+            "description": "Organization or SSO config not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -8287,63 +8505,57 @@
             }
           }
         }
-      }
-    },
-    "/admin/v1/organizations/{slug}/usage": {
-      "get": {
+      },
+      "patch": {
         "tags": [
-          "usage"
+          "sso"
         ],
-        "summary": "Get usage summary for an organization",
-        "operationId": "usage_get_org_summary",
+        "summary": "Update the SSO configuration for an organization",
+        "operationId": "org_sso_config_update",
         "parameters": [
           {
-            "name": "slug",
+            "name": "org_slug",
             "in": "path",
             "description": "Organization slug",
             "required": true,
             "schema": {
               "type": "string"
             }
-          },
-          {
-            "name": "start_date",
-            "in": "query",
-            "description": "Start date (YYYY-MM-DD)",
-            "required": false,
-            "schema": {
-              "type": [
-                "string",
-                "null"
-              ]
-            }
-          },
-          {
-            "name": "end_date",
-            "in": "query",
-            "description": "End date (YYYY-MM-DD)",
-            "required": false,
-            "schema": {
-              "type": [
-                "string",
-                "null"
-              ]
-            }
           }
         ],
+        "requestBody": {
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/UpdateOrgSsoConfig"
+              }
+            }
+          },
+          "required": true
+        },
         "responses": {
           "200": {
-            "description": "Usage summary",
+            "description": "SSO config updated",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/UsageSummaryResponse"
+                  "$ref": "#/components/schemas/OrgSsoConfig"
+                }
+              }
+            }
+          },
+          "403": {
+            "description": "Access denied",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
                 }
               }
             }
           },
           "404": {
-            "description": "Organization not found",
+            "description": "Organization or SSO config not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -8355,16 +8567,16 @@
         }
       }
     },
-    "/admin/v1/organizations/{slug}/usage/by-date": {
+    "/admin/v1/organizations/{org_slug}/sso-config/domains": {
       "get": {
         "tags": [
-          "usage"
+          "domain-verifications"
         ],
-        "summary": "Get usage by date for an organization",
-        "operationId": "usage_get_org_by_date",
+        "summary": "List all domain verifications for an organization's SSO config",
+        "operationId": "domain_verifications_list",
         "parameters": [
           {
-            "name": "slug",
+            "name": "org_slug",
             "in": "path",
             "description": "Organization slug",
             "required": true,
@@ -8373,46 +8585,39 @@
             }
           },
           {
-            "name": "start_date",
-            "in": "query",
-            "description": "Start date (YYYY-MM-DD)",
-            "required": false,
-            "schema": {
-              "type": [
-                "string",
-                "null"
-              ]
-            }
-          },
-          {
-            "name": "end_date",
+            "name": "limit",
             "in": "query",
-            "description": "End date (YYYY-MM-DD)",
+            "description": "Maximum number of items to return",
             "required": false,
             "schema": {
-              "type": [
-                "string",
-                "null"
-              ]
+              "type": "integer",
+              "format": "int64"
             }
           }
         ],
         "responses": {
           "200": {
-            "description": "Daily usage breakdown",
+            "description": "Domain verifications list",
             "content": {
               "application/json": {
                 "schema": {
-                  "type": "array",
-                  "items": {
-                    "$ref": "#/components/schemas/DailySpendResponse"
-                  }
+                  "$ref": "#/components/schemas/ListDomainVerificationsResponse"
+                }
+              }
+            }
+          },
+          "403": {
+            "description": "Access denied",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
                 }
               }
             }
           },
           "404": {
-            "description": "Organization not found",
+            "description": "Organization or SSO config not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -8422,66 +8627,78 @@
             }
           }
         }
-      }
-    },
-    "/admin/v1/organizations/{slug}/usage/by-model": {
-      "get": {
+      },
+      "post": {
         "tags": [
-          "usage"
+          "domain-verifications"
         ],
-        "summary": "Get usage by model for an organization",
-        "operationId": "usage_get_org_by_model",
+        "summary": "Initiate domain verification for an organization's SSO config",
+        "description": "Creates a new domain verification record with a unique verification token.\nReturns the verification instructions with DNS record details.",
+        "operationId": "domain_verifications_create",
         "parameters": [
           {
-            "name": "slug",
+            "name": "org_slug",
             "in": "path",
             "description": "Organization slug",
             "required": true,
             "schema": {
               "type": "string"
             }
+          }
+        ],
+        "requestBody": {
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/CreateDomainVerification"
+              }
+            }
           },
-          {
-            "name": "start_date",
-            "in": "query",
-            "description": "Start date (YYYY-MM-DD)",
-            "required": false,
-            "schema": {
-              "type": [
-                "string",
-                "null"
-              ]
+          "required": true
+        },
+        "responses": {
+          "201": {
+            "description": "Domain verification initiated",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/DomainVerification"
+                }
+              }
             }
           },
-          {
-            "name": "end_date",
-            "in": "query",
-            "description": "End date (YYYY-MM-DD)",
-            "required": false,
-            "schema": {
-              "type": [
-                "string",
-                "null"
-              ]
+          "400": {
+            "description": "Invalid domain or public domain blocked",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
             }
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "Usage breakdown by model",
+          },
+          "403": {
+            "description": "Access denied",
             "content": {
               "application/json": {
                 "schema": {
-                  "type": "array",
-                  "items": {
-                    "$ref": "#/components/schemas/ModelSpendResponse"
-                  }
+                  "$ref": "#/components/schemas/ErrorResponse"
                 }
               }
             }
           },
           "404": {
-            "description": "Organization not found",
+            "description": "Organization or SSO config not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "409": {
+            "description": "Domain already being verified",
             "content": {
               "application/json": {
                 "schema": {
@@ -8493,16 +8710,16 @@
         }
       }
     },
-    "/admin/v1/organizations/{slug}/usage/by-provider": {
+    "/admin/v1/organizations/{org_slug}/sso-config/domains/{domain_id}": {
       "get": {
         "tags": [
-          "usage"
+          "domain-verifications"
         ],
-        "summary": "Get usage by provider for an organization",
-        "operationId": "usage_get_org_by_provider",
+        "summary": "Get a specific domain verification by ID",
+        "operationId": "domain_verifications_get",
         "parameters": [
           {
-            "name": "slug",
+            "name": "org_slug",
             "in": "path",
             "description": "Organization slug",
             "required": true,
@@ -8511,46 +8728,39 @@
             }
           },
           {
-            "name": "start_date",
-            "in": "query",
-            "description": "Start date (YYYY-MM-DD)",
-            "required": false,
-            "schema": {
-              "type": [
-                "string",
-                "null"
-              ]
-            }
-          },
-          {
-            "name": "end_date",
-            "in": "query",
-            "description": "End date (YYYY-MM-DD)",
-            "required": false,
+            "name": "domain_id",
+            "in": "path",
+            "description": "Domain verification ID",
+            "required": true,
             "schema": {
-              "type": [
-                "string",
-                "null"
-              ]
+              "type": "string",
+              "format": "uuid"
             }
           }
         ],
         "responses": {
           "200": {
-            "description": "Usage breakdown by provider",
+            "description": "Domain verification found",
             "content": {
               "application/json": {
                 "schema": {
-                  "type": "array",
-                  "items": {
-                    "$ref": "#/components/schemas/ProviderSpendResponse"
-                  }
+                  "$ref": "#/components/schemas/DomainVerification"
+                }
+              }
+            }
+          },
+          "403": {
+            "description": "Access denied",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
                 }
               }
             }
           },
           "404": {
-            "description": "Organization not found",
+            "description": "Organization, SSO config, or domain verification not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -8560,19 +8770,16 @@
             }
           }
         }
-      }
-    },
-    "/admin/v1/organizations/{slug}/usage/forecast": {
-      "get": {
+      },
+      "delete": {
         "tags": [
-          "usage"
+          "domain-verifications"
         ],
-        "summary": "Get cost forecast for an organization",
-        "description": "Uses historical usage data across all API keys in the organization to predict future spending.\nReturns average daily spend, confidence intervals, and time series forecasts.",
-        "operationId": "usage_get_org_forecast",
+        "summary": "Delete a domain verification",
+        "operationId": "domain_verifications_delete",
         "parameters": [
           {
-            "name": "slug",
+            "name": "org_slug",
             "in": "path",
             "description": "Organization slug",
             "required": true,
@@ -8581,45 +8788,32 @@
             }
           },
           {
-            "name": "lookback_days",
-            "in": "query",
-            "description": "Number of days of historical data to use (default: 30)",
-            "required": false,
-            "schema": {
-              "type": [
-                "integer",
-                "null"
-              ],
-              "format": "int32"
-            }
-          },
-          {
-            "name": "forecast_days",
-            "in": "query",
-            "description": "Number of days to forecast ahead (default: 7)",
-            "required": false,
+            "name": "domain_id",
+            "in": "path",
+            "description": "Domain verification ID",
+            "required": true,
             "schema": {
-              "type": [
-                "integer",
-                "null"
-              ],
-              "minimum": 0
+              "type": "string",
+              "format": "uuid"
             }
           }
         ],
         "responses": {
           "200": {
-            "description": "Cost forecast",
+            "description": "Domain verification deleted"
+          },
+          "403": {
+            "description": "Access denied",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/CostForecastResponse"
+                  "$ref": "#/components/schemas/ErrorResponse"
                 }
               }
             }
           },
           "404": {
-            "description": "Organization not found",
+            "description": "Organization, SSO config, or domain verification not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -8631,36 +8825,47 @@
         }
       }
     },
-    "/admin/v1/prompts": {
-      "post": {
+    "/admin/v1/organizations/{org_slug}/sso-config/domains/{domain_id}/instructions": {
+      "get": {
         "tags": [
-          "prompts"
+          "domain-verifications"
         ],
-        "summary": "Create a prompt template",
-        "operationId": "prompt_create",
-        "requestBody": {
-          "content": {
-            "application/json": {
-              "schema": {
-                "$ref": "#/components/schemas/CreatePrompt"
-              }
+        "summary": "Get verification instructions for a domain",
+        "operationId": "domain_verifications_get_instructions",
+        "parameters": [
+          {
+            "name": "org_slug",
+            "in": "path",
+            "description": "Organization slug",
+            "required": true,
+            "schema": {
+              "type": "string"
             }
           },
-          "required": true
-        },
+          {
+            "name": "domain_id",
+            "in": "path",
+            "description": "Domain verification ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          }
+        ],
         "responses": {
-          "201": {
-            "description": "Prompt created",
+          "200": {
+            "description": "Verification instructions",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/Prompt"
+                  "$ref": "#/components/schemas/DomainVerificationInstructions"
                 }
               }
             }
           },
-          "404": {
-            "description": "Owner not found",
+          "403": {
+            "description": "Access denied",
             "content": {
               "application/json": {
                 "schema": {
@@ -8669,8 +8874,8 @@
               }
             }
           },
-          "409": {
-            "description": "Prompt with this name already exists",
+          "404": {
+            "description": "Organization, SSO config, or domain verification not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -8682,18 +8887,28 @@
         }
       }
     },
-    "/admin/v1/prompts/{id}": {
-      "get": {
+    "/admin/v1/organizations/{org_slug}/sso-config/domains/{domain_id}/verify": {
+      "post": {
         "tags": [
-          "prompts"
+          "domain-verifications"
         ],
-        "summary": "Get a prompt by ID",
-        "operationId": "prompt_get",
+        "summary": "Trigger DNS verification for a domain",
+        "description": "Performs a DNS TXT record lookup to verify domain ownership.",
+        "operationId": "domain_verifications_verify",
         "parameters": [
           {
-            "name": "id",
+            "name": "org_slug",
+            "in": "path",
+            "description": "Organization slug",
+            "required": true,
+            "schema": {
+              "type": "string"
+            }
+          },
+          {
+            "name": "domain_id",
             "in": "path",
-            "description": "Prompt ID",
+            "description": "Domain verification ID",
             "required": true,
             "schema": {
               "type": "string",
@@ -8703,17 +8918,27 @@
         ],
         "responses": {
           "200": {
-            "description": "Prompt found",
+            "description": "Verification attempt result",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/VerifyDomainResponse"
+                }
+              }
+            }
+          },
+          "403": {
+            "description": "Access denied",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/Prompt"
+                  "$ref": "#/components/schemas/ErrorResponse"
                 }
               }
             }
           },
           "404": {
-            "description": "Prompt not found",
+            "description": "Organization, SSO config, or domain verification not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -8723,31 +8948,108 @@
             }
           }
         }
-      },
-      "delete": {
+      }
+    },
+    "/admin/v1/organizations/{org_slug}/sso-group-mappings": {
+      "get": {
         "tags": [
-          "prompts"
+          "sso"
         ],
-        "summary": "Delete a prompt",
-        "operationId": "prompt_delete",
+        "summary": "List SSO group mappings for an organization",
+        "operationId": "sso_group_mapping_list",
         "parameters": [
           {
-            "name": "id",
+            "name": "org_slug",
             "in": "path",
-            "description": "Prompt ID",
+            "description": "Organization slug",
             "required": true,
             "schema": {
-              "type": "string",
-              "format": "uuid"
+              "type": "string"
+            }
+          },
+          {
+            "name": "limit",
+            "in": "query",
+            "description": "Maximum number of results to return",
+            "required": false,
+            "schema": {
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "int64"
+            }
+          },
+          {
+            "name": "cursor",
+            "in": "query",
+            "description": "Cursor for keyset pagination. Encoded as base64 string.",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "direction",
+            "in": "query",
+            "description": "Pagination direction: \"forward\" (default) or \"backward\".",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "include_deleted",
+            "in": "query",
+            "description": "Include soft-deleted records in results",
+            "required": false,
+            "schema": {
+              "type": [
+                "boolean",
+                "null"
+              ]
             }
           }
         ],
         "responses": {
           "200": {
-            "description": "Prompt deleted"
+            "description": "List of SSO group mappings",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/SsoGroupMappingListResponse"
+                }
+              }
+            }
+          },
+          "400": {
+            "description": "Invalid cursor or direction",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "403": {
+            "description": "Access denied",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
           },
           "404": {
-            "description": "Prompt not found",
+            "description": "Organization not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -8758,21 +9060,20 @@
           }
         }
       },
-      "patch": {
+      "post": {
         "tags": [
-          "prompts"
+          "sso"
         ],
-        "summary": "Update a prompt",
-        "operationId": "prompt_update",
+        "summary": "Create a new SSO group mapping",
+        "operationId": "sso_group_mapping_create",
         "parameters": [
           {
-            "name": "id",
+            "name": "org_slug",
             "in": "path",
-            "description": "Prompt ID",
+            "description": "Organization slug",
             "required": true,
             "schema": {
-              "type": "string",
-              "format": "uuid"
+              "type": "string"
             }
           }
         ],
@@ -8780,25 +9081,25 @@
           "content": {
             "application/json": {
               "schema": {
-                "$ref": "#/components/schemas/UpdatePrompt"
+                "$ref": "#/components/schemas/CreateSsoGroupMapping"
               }
             }
           },
           "required": true
         },
         "responses": {
-          "200": {
-            "description": "Prompt updated",
+          "201": {
+            "description": "SSO group mapping created",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/Prompt"
+                  "$ref": "#/components/schemas/SsoGroupMapping"
                 }
               }
             }
           },
-          "404": {
-            "description": "Prompt not found",
+          "403": {
+            "description": "Access denied",
             "content": {
               "application/json": {
                 "schema": {
@@ -8807,8 +9108,8 @@
               }
             }
           },
-          "409": {
-            "description": "Prompt with this name already exists",
+          "404": {
+            "description": "Organization not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -8820,306 +9121,400 @@
         }
       }
     },
-    "/admin/v1/providers/circuit-breakers": {
+    "/admin/v1/organizations/{org_slug}/sso-group-mappings/export": {
       "get": {
         "tags": [
-          "providers"
+          "sso"
         ],
-        "summary": "Get circuit breaker status for all providers.",
-        "description": "Returns the current state and failure count for all configured\ncircuit breakers. Useful for monitoring provider health.",
-        "operationId": "list_circuit_breakers",
-        "responses": {
-          "200": {
-            "description": "Circuit breaker status for all providers",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/CircuitBreakersResponse"
-                }
-              }
+        "summary": "Export SSO group mappings",
+        "description": "Exports all SSO group mappings for an organization in JSON or CSV format.\nUseful for backup, migration, or bulk editing in a spreadsheet.",
+        "operationId": "sso_group_mapping_export",
+        "parameters": [
+          {
+            "name": "org_slug",
+            "in": "path",
+            "description": "Organization slug",
+            "required": true,
+            "schema": {
+              "type": "string"
+            }
+          },
+          {
+            "name": "format",
+            "in": "query",
+            "description": "Export format (json or csv, defaults to json)",
+            "required": false,
+            "schema": {
+              "$ref": "#/components/schemas/ExportFormat"
+            }
+          },
+          {
+            "name": "sso_connection_name",
+            "in": "query",
+            "description": "Filter by SSO connection name (optional)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
             }
           }
-        }
-      }
-    },
-    "/admin/v1/providers/health": {
-      "get": {
-        "tags": [
-          "providers"
         ],
-        "summary": "Get health status for all providers.",
-        "description": "Returns the current health status for all providers that have health checks\nenabled. Includes status, latency, last check time, and consecutive\nsuccess/failure counts.\n\nNote: Only providers with `health_check.enabled = true` in their config\nwill appear in this list. Providers without health checks rely solely\non circuit breaker status.",
-        "operationId": "list_provider_health",
         "responses": {
           "200": {
-            "description": "Health status for all providers",
+            "description": "Export of SSO group mappings as CSV",
+            "content": {
+              "text/csv": {}
+            }
+          },
+          "403": {
+            "description": "Access denied",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ProviderHealthResponse"
+                  "$ref": "#/components/schemas/ErrorResponse"
                 }
               }
             }
-          }
-        }
-      }
-    },
-    "/admin/v1/providers/stats": {
-      "get": {
-        "tags": [
-          "providers"
-        ],
-        "summary": "Get aggregated statistics for all providers.",
-        "description": "Returns current metrics including latency percentiles, error counts,\ntoken usage, and costs for all providers.\n\nIn single-node deployments, stats are derived from the local /metrics endpoint.\nIn multi-node deployments with Prometheus configured, stats are aggregated\nfrom Prometheus queries.",
-        "operationId": "list_provider_stats",
-        "responses": {
-          "200": {
-            "description": "Stats for all providers",
+          },
+          "404": {
+            "description": "Organization not found",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ProviderStatsResponse"
+                  "$ref": "#/components/schemas/ErrorResponse"
                 }
               }
             }
-          },
-          "500": {
-            "description": "Failed to fetch stats"
           }
         }
       }
     },
-    "/admin/v1/providers/{provider_name}/circuit-breaker": {
-      "get": {
+    "/admin/v1/organizations/{org_slug}/sso-group-mappings/import": {
+      "post": {
         "tags": [
-          "providers"
+          "sso"
         ],
-        "summary": "Get circuit breaker status for a specific provider.",
-        "description": "Returns the current state and failure count for the specified provider's\ncircuit breaker.",
-        "operationId": "get_circuit_breaker",
+        "summary": "Import SSO group mappings",
+        "description": "Bulk import SSO group mappings from a JSON payload. Useful for migrating\nmappings between environments or restoring from a backup.",
+        "operationId": "sso_group_mapping_import",
         "parameters": [
           {
-            "name": "provider_name",
+            "name": "org_slug",
             "in": "path",
-            "description": "Provider name",
+            "description": "Organization slug",
             "required": true,
             "schema": {
               "type": "string"
             }
           }
         ],
+        "requestBody": {
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/ImportRequest"
+              }
+            }
+          },
+          "required": true
+        },
         "responses": {
           "200": {
-            "description": "Circuit breaker status for the provider",
+            "description": "Import completed",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ProviderCircuitBreakerResponse"
+                  "$ref": "#/components/schemas/ImportResponse"
+                }
+              }
+            }
+          },
+          "400": {
+            "description": "Invalid request or conflict error",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "403": {
+            "description": "Access denied",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
                 }
               }
             }
           },
           "404": {
-            "description": "Provider not found or circuit breaker not enabled"
+            "description": "Organization not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
           }
         }
       }
     },
-    "/admin/v1/providers/{provider_name}/health": {
-      "get": {
+    "/admin/v1/organizations/{org_slug}/sso-group-mappings/test": {
+      "post": {
         "tags": [
-          "providers"
+          "sso"
         ],
-        "summary": "Get health status for a specific provider.",
-        "description": "Returns the current health status for the specified provider. Only works\nfor providers that have health checks enabled.",
-        "operationId": "get_provider_health",
+        "summary": "Test SSO group mapping resolution",
+        "description": "Given a list of IdP group names, returns what teams/roles a user with those\ngroups would be resolved to. This is useful for debugging and verifying\nmapping configuration.",
+        "operationId": "sso_group_mapping_test",
         "parameters": [
           {
-            "name": "provider_name",
+            "name": "org_slug",
             "in": "path",
-            "description": "Provider name",
+            "description": "Organization slug",
             "required": true,
             "schema": {
               "type": "string"
             }
           }
         ],
+        "requestBody": {
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/TestMappingRequest"
+              }
+            }
+          },
+          "required": true
+        },
         "responses": {
           "200": {
-            "description": "Health status for the provider",
+            "description": "Mapping test results",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ProviderHealthState"
+                  "$ref": "#/components/schemas/TestMappingResponse"
+                }
+              }
+            }
+          },
+          "400": {
+            "description": "Invalid request",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "403": {
+            "description": "Access denied",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
                 }
               }
             }
           },
           "404": {
-            "description": "Provider not found or health checks not enabled"
+            "description": "Organization not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
           }
         }
       }
     },
-    "/admin/v1/providers/{provider_name}/stats": {
+    "/admin/v1/organizations/{org_slug}/sso-group-mappings/{mapping_id}": {
       "get": {
         "tags": [
-          "providers"
+          "sso"
         ],
-        "summary": "Get aggregated statistics for a specific provider.",
-        "description": "Returns current metrics including latency percentiles, error counts,\ntoken usage, and costs for the specified provider.",
-        "operationId": "get_provider_stats",
+        "summary": "Get an SSO group mapping by ID",
+        "operationId": "sso_group_mapping_get",
         "parameters": [
           {
-            "name": "provider_name",
+            "name": "org_slug",
             "in": "path",
-            "description": "Provider name",
+            "description": "Organization slug",
             "required": true,
             "schema": {
               "type": "string"
             }
+          },
+          {
+            "name": "mapping_id",
+            "in": "path",
+            "description": "Mapping ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
           }
         ],
         "responses": {
           "200": {
-            "description": "Stats for the provider",
+            "description": "SSO group mapping found",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ProviderStats"
+                  "$ref": "#/components/schemas/SsoGroupMapping"
+                }
+              }
+            }
+          },
+          "403": {
+            "description": "Access denied",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
                 }
               }
             }
           },
           "404": {
-            "description": "Provider not found or no stats available"
+            "description": "Organization or mapping not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
           }
         }
-      }
-    },
-    "/admin/v1/providers/{provider_name}/stats/history": {
-      "get": {
+      },
+      "delete": {
         "tags": [
-          "providers"
+          "sso"
         ],
-        "summary": "Get historical statistics for a specific provider.",
-        "description": "Returns time series data for the specified provider within the given\ntime range. Data is returned as hourly or daily buckets depending\non the granularity parameter.\n\n**Note:** Historical stats require Prometheus to be configured via\n`observability.metrics.prometheus_query_url`. In single-node deployments\nwithout Prometheus, this endpoint returns an error.",
-        "operationId": "get_provider_stats_history",
+        "summary": "Delete an SSO group mapping",
+        "operationId": "sso_group_mapping_delete",
         "parameters": [
           {
-            "name": "provider_name",
+            "name": "org_slug",
             "in": "path",
-            "description": "Provider name",
+            "description": "Organization slug",
             "required": true,
             "schema": {
               "type": "string"
             }
           },
           {
-            "name": "start",
-            "in": "query",
-            "description": "Start of the time range (defaults to 24 hours ago).",
-            "required": false,
-            "schema": {
-              "type": [
-                "string",
-                "null"
-              ],
-              "format": "date-time"
-            }
-          },
-          {
-            "name": "end",
-            "in": "query",
-            "description": "End of the time range (defaults to now).",
-            "required": false,
-            "schema": {
-              "type": [
-                "string",
-                "null"
-              ],
-              "format": "date-time"
-            }
-          },
-          {
-            "name": "granularity",
-            "in": "query",
-            "description": "Granularity of the data points: \"hour\" or \"day\" (defaults to \"hour\").",
-            "required": false,
+            "name": "mapping_id",
+            "in": "path",
+            "description": "Mapping ID",
+            "required": true,
             "schema": {
-              "type": [
-                "string",
-                "null"
-              ]
+              "type": "string",
+              "format": "uuid"
             }
           }
         ],
         "responses": {
           "200": {
-            "description": "Historical stats for the provider",
+            "description": "SSO group mapping deleted"
+          },
+          "403": {
+            "description": "Access denied",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ProviderStatsHistorical"
+                  "$ref": "#/components/schemas/ErrorResponse"
                 }
               }
             }
           },
-          "400": {
-            "description": "Invalid query parameters or Prometheus not configured"
+          "404": {
+            "description": "Organization or mapping not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
           }
         }
-      }
-    },
-    "/admin/v1/providers/{provider}/usage": {
-      "get": {
+      },
+      "patch": {
         "tags": [
-          "usage"
+          "sso"
         ],
-        "summary": "Get usage summary for a provider",
-        "operationId": "usage_get_provider_summary",
+        "summary": "Update an SSO group mapping",
+        "operationId": "sso_group_mapping_update",
         "parameters": [
           {
-            "name": "provider",
+            "name": "org_slug",
             "in": "path",
-            "description": "Provider name",
+            "description": "Organization slug",
             "required": true,
             "schema": {
               "type": "string"
             }
           },
           {
-            "name": "start_date",
-            "in": "query",
-            "description": "Start date (YYYY-MM-DD)",
-            "required": false,
-            "schema": {
-              "type": [
-                "string",
-                "null"
-              ]
-            }
-          },
-          {
-            "name": "end_date",
-            "in": "query",
-            "description": "End date (YYYY-MM-DD)",
-            "required": false,
+            "name": "mapping_id",
+            "in": "path",
+            "description": "Mapping ID",
+            "required": true,
             "schema": {
-              "type": [
-                "string",
-                "null"
-              ]
+              "type": "string",
+              "format": "uuid"
             }
           }
         ],
+        "requestBody": {
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/UpdateSsoGroupMapping"
+              }
+            }
+          },
+          "required": true
+        },
         "responses": {
           "200": {
-            "description": "Usage summary",
+            "description": "SSO group mapping updated",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/UsageSummaryResponse"
+                  "$ref": "#/components/schemas/SsoGroupMapping"
+                }
+              }
+            }
+          },
+          "403": {
+            "description": "Access denied",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "404": {
+            "description": "Organization or mapping not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
                 }
               }
             }
@@ -9127,39 +9522,40 @@
         }
       }
     },
-    "/admin/v1/providers/{provider}/usage/by-date": {
+    "/admin/v1/organizations/{org_slug}/teams": {
       "get": {
         "tags": [
-          "usage"
+          "teams"
         ],
-        "summary": "Get usage by date for a provider",
-        "operationId": "usage_get_provider_by_date",
+        "summary": "List teams in an organization",
+        "operationId": "team_list",
         "parameters": [
           {
-            "name": "provider",
+            "name": "org_slug",
             "in": "path",
-            "description": "Provider name",
+            "description": "Organization slug",
             "required": true,
             "schema": {
               "type": "string"
             }
           },
           {
-            "name": "start_date",
+            "name": "limit",
             "in": "query",
-            "description": "Start date (YYYY-MM-DD)",
+            "description": "Maximum number of results to return",
             "required": false,
             "schema": {
               "type": [
-                "string",
+                "integer",
                 "null"
-              ]
+              ],
+              "format": "int64"
             }
           },
           {
-            "name": "end_date",
+            "name": "cursor",
             "in": "query",
-            "description": "End date (YYYY-MM-DD)",
+            "description": "Cursor for keyset pagination. Encoded as base64 string.",
             "required": false,
             "schema": {
               "type": [
@@ -9167,46 +9563,11 @@
                 "null"
               ]
             }
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "Daily usage breakdown",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "type": "array",
-                  "items": {
-                    "$ref": "#/components/schemas/DailySpendResponse"
-                  }
-                }
-              }
-            }
-          }
-        }
-      }
-    },
-    "/admin/v1/providers/{provider}/usage/by-model": {
-      "get": {
-        "tags": [
-          "usage"
-        ],
-        "summary": "Get usage by model for a provider",
-        "operationId": "usage_get_provider_by_model",
-        "parameters": [
-          {
-            "name": "provider",
-            "in": "path",
-            "description": "Provider name",
-            "required": true,
-            "schema": {
-              "type": "string"
-            }
           },
           {
-            "name": "start_date",
+            "name": "direction",
             "in": "query",
-            "description": "Start date (YYYY-MM-DD)",
+            "description": "Pagination direction: \"forward\" (default) or \"backward\".",
             "required": false,
             "schema": {
               "type": [
@@ -9216,13 +9577,13 @@
             }
           },
           {
-            "name": "end_date",
+            "name": "include_deleted",
             "in": "query",
-            "description": "End date (YYYY-MM-DD)",
+            "description": "Include soft-deleted records in results",
             "required": false,
             "schema": {
               "type": [
-                "string",
+                "boolean",
                 "null"
               ]
             }
@@ -9230,105 +9591,81 @@
         ],
         "responses": {
           "200": {
-            "description": "Usage breakdown by model",
+            "description": "List of teams",
             "content": {
               "application/json": {
                 "schema": {
-                  "type": "array",
-                  "items": {
-                    "$ref": "#/components/schemas/ModelSpendResponse"
-                  }
+                  "$ref": "#/components/schemas/TeamListResponse"
+                }
+              }
+            }
+          },
+          "400": {
+            "description": "Invalid cursor or direction",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "403": {
+            "description": "Access denied",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "404": {
+            "description": "Organization not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
                 }
               }
             }
           }
         }
-      }
-    },
-    "/admin/v1/providers/{provider}/usage/forecast": {
-      "get": {
+      },
+      "post": {
         "tags": [
-          "usage"
+          "teams"
         ],
-        "summary": "Get cost forecast for a provider",
-        "description": "Uses historical usage data across all API keys using this provider to predict future spending.\nReturns average daily spend, confidence intervals, and time series forecasts.",
-        "operationId": "usage_get_provider_forecast",
+        "summary": "Create a team in an organization",
+        "operationId": "team_create",
         "parameters": [
           {
-            "name": "provider",
+            "name": "org_slug",
             "in": "path",
-            "description": "Provider name",
+            "description": "Organization slug",
             "required": true,
             "schema": {
               "type": "string"
             }
-          },
-          {
-            "name": "lookback_days",
-            "in": "query",
-            "description": "Number of days of historical data to use (default: 30)",
-            "required": false,
-            "schema": {
-              "type": [
-                "integer",
-                "null"
-              ],
-              "format": "int32"
-            }
-          },
-          {
-            "name": "forecast_days",
-            "in": "query",
-            "description": "Number of days to forecast ahead (default: 7)",
-            "required": false,
-            "schema": {
-              "type": [
-                "integer",
-                "null"
-              ],
-              "minimum": 0
-            }
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "Cost forecast",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/CostForecastResponse"
-                }
-              }
-            }
           }
-        }
-      }
-    },
-    "/admin/v1/rbac-policies/validate": {
-      "post": {
-        "tags": [
-          "rbac-policies"
         ],
-        "summary": "Validate a CEL expression",
-        "description": "Checks if a CEL expression is syntactically valid without creating a policy.\nUseful for validating expressions before saving.",
-        "operationId": "org_rbac_policy_validate",
         "requestBody": {
           "content": {
             "application/json": {
               "schema": {
-                "$ref": "#/components/schemas/ValidateCelRequest"
+                "$ref": "#/components/schemas/CreateTeam"
               }
             }
           },
           "required": true
         },
         "responses": {
-          "200": {
-            "description": "Validation result",
+          "201": {
+            "description": "Team created",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ValidateCelResponse"
+                  "$ref": "#/components/schemas/Team"
                 }
               }
             }
@@ -9342,31 +9679,80 @@
                 }
               }
             }
+          },
+          "404": {
+            "description": "Organization not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "409": {
+            "description": "Conflict (slug already exists)",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
           }
         }
       }
     },
-    "/admin/v1/session-info": {
+    "/admin/v1/organizations/{org_slug}/teams/{team_slug}": {
       "get": {
         "tags": [
-          "session"
+          "teams"
+        ],
+        "summary": "Get a team by slug",
+        "operationId": "team_get",
+        "parameters": [
+          {
+            "name": "org_slug",
+            "in": "path",
+            "description": "Organization slug",
+            "required": true,
+            "schema": {
+              "type": "string"
+            }
+          },
+          {
+            "name": "team_slug",
+            "in": "path",
+            "description": "Team slug",
+            "required": true,
+            "schema": {
+              "type": "string"
+            }
+          }
         ],
-        "summary": "Get comprehensive session and access information.",
-        "description": "Returns detailed information about the current user's authentication state,\ndatabase profile, organization/team/project memberships, and SSO configuration.\nUseful for debugging authentication and authorization issues.",
-        "operationId": "session_info_get",
         "responses": {
           "200": {
-            "description": "Session information",
+            "description": "Team found",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/SessionInfoResponse"
+                  "$ref": "#/components/schemas/Team"
                 }
               }
             }
           },
-          "401": {
-            "description": "Not authenticated",
+          "403": {
+            "description": "Access denied",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "404": {
+            "description": "Organization or team not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -9376,29 +9762,49 @@
             }
           }
         }
-      }
-    },
-    "/admin/v1/sso-connections": {
-      "get": {
+      },
+      "delete": {
         "tags": [
-          "sso"
+          "teams"
+        ],
+        "summary": "Delete a team",
+        "operationId": "team_delete",
+        "parameters": [
+          {
+            "name": "org_slug",
+            "in": "path",
+            "description": "Organization slug",
+            "required": true,
+            "schema": {
+              "type": "string"
+            }
+          },
+          {
+            "name": "team_slug",
+            "in": "path",
+            "description": "Team slug",
+            "required": true,
+            "schema": {
+              "type": "string"
+            }
+          }
         ],
-        "summary": "List configured SSO connections",
-        "description": "Returns read-only information about SSO connections configured in the gateway.\nSSO connections are defined in the config file (gateway.toml), not the database.\nCurrently only one OIDC connection is supported per deployment.",
-        "operationId": "sso_connections_list",
         "responses": {
           "200": {
-            "description": "List of SSO connections",
+            "description": "Team deleted"
+          },
+          "403": {
+            "description": "Access denied",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/SsoConnectionsResponse"
+                  "$ref": "#/components/schemas/ErrorResponse"
                 }
               }
             }
           },
-          "403": {
-            "description": "Access denied",
+          "404": {
+            "description": "Organization or team not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -9408,33 +9814,50 @@
             }
           }
         }
-      }
-    },
-    "/admin/v1/sso-connections/{name}": {
-      "get": {
+      },
+      "patch": {
         "tags": [
-          "sso"
+          "teams"
         ],
-        "summary": "Get a specific SSO connection by name",
-        "operationId": "sso_connection_get",
+        "summary": "Update a team",
+        "operationId": "team_update",
         "parameters": [
           {
-            "name": "name",
+            "name": "org_slug",
             "in": "path",
-            "description": "SSO connection name",
+            "description": "Organization slug",
+            "required": true,
+            "schema": {
+              "type": "string"
+            }
+          },
+          {
+            "name": "team_slug",
+            "in": "path",
+            "description": "Team slug",
             "required": true,
             "schema": {
               "type": "string"
             }
           }
         ],
+        "requestBody": {
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/UpdateTeam"
+              }
+            }
+          },
+          "required": true
+        },
         "responses": {
           "200": {
-            "description": "SSO connection found",
+            "description": "Team updated",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/SsoConnection"
+                  "$ref": "#/components/schemas/Team"
                 }
               }
             }
@@ -9450,7 +9873,7 @@
             }
           },
           "404": {
-            "description": "SSO connection not found",
+            "description": "Organization or team not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -9462,14 +9885,32 @@
         }
       }
     },
-    "/admin/v1/users": {
+    "/admin/v1/organizations/{org_slug}/teams/{team_slug}/members": {
       "get": {
         "tags": [
-          "users"
+          "teams"
         ],
-        "summary": "List all users",
-        "operationId": "user_list",
+        "summary": "List team members",
+        "operationId": "team_member_list",
         "parameters": [
+          {
+            "name": "org_slug",
+            "in": "path",
+            "description": "Organization slug",
+            "required": true,
+            "schema": {
+              "type": "string"
+            }
+          },
+          {
+            "name": "team_slug",
+            "in": "path",
+            "description": "Team slug",
+            "required": true,
+            "schema": {
+              "type": "string"
+            }
+          },
           {
             "name": "limit",
             "in": "query",
@@ -9522,11 +9963,11 @@
         ],
         "responses": {
           "200": {
-            "description": "List of users",
+            "description": "List of team members",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/UserListResponse"
+                  "$ref": "#/components/schemas/TeamMemberListResponse"
                 }
               }
             }
@@ -9550,20 +9991,50 @@
                 }
               }
             }
+          },
+          "404": {
+            "description": "Organization or team not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
           }
         }
       },
       "post": {
         "tags": [
-          "users"
+          "teams"
         ],
-        "summary": "Create a user",
-        "operationId": "user_create",
-        "requestBody": {
-          "content": {
-            "application/json": {
+        "summary": "Add a member to a team",
+        "operationId": "team_member_add",
+        "parameters": [
+          {
+            "name": "org_slug",
+            "in": "path",
+            "description": "Organization slug",
+            "required": true,
+            "schema": {
+              "type": "string"
+            }
+          },
+          {
+            "name": "team_slug",
+            "in": "path",
+            "description": "Team slug",
+            "required": true,
+            "schema": {
+              "type": "string"
+            }
+          }
+        ],
+        "requestBody": {
+          "content": {
+            "application/json": {
               "schema": {
-                "$ref": "#/components/schemas/CreateUser"
+                "$ref": "#/components/schemas/AddTeamMember"
               }
             }
           },
@@ -9571,11 +10042,11 @@
         },
         "responses": {
           "201": {
-            "description": "User created",
+            "description": "Member added",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/User"
+                  "$ref": "#/components/schemas/TeamMember"
                 }
               }
             }
@@ -9590,8 +10061,18 @@
               }
             }
           },
+          "404": {
+            "description": "Organization, team, or user not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
           "409": {
-            "description": "Conflict (external_id already exists)",
+            "description": "User is already a member",
             "content": {
               "application/json": {
                 "schema": {
@@ -9603,66 +10084,32 @@
         }
       }
     },
-    "/admin/v1/users/{user_id}": {
-      "get": {
+    "/admin/v1/organizations/{org_slug}/teams/{team_slug}/members/{user_id}": {
+      "delete": {
         "tags": [
-          "users"
+          "teams"
         ],
-        "summary": "Get a user by ID",
-        "operationId": "user_get",
+        "summary": "Remove a member from a team",
+        "operationId": "team_member_remove",
         "parameters": [
           {
-            "name": "user_id",
+            "name": "org_slug",
             "in": "path",
-            "description": "User ID",
+            "description": "Organization slug",
             "required": true,
             "schema": {
-              "type": "string",
-              "format": "uuid"
-            }
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "User found",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/User"
-                }
-              }
+              "type": "string"
             }
           },
-          "403": {
-            "description": "Access denied",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
+          {
+            "name": "team_slug",
+            "in": "path",
+            "description": "Team slug",
+            "required": true,
+            "schema": {
+              "type": "string"
             }
           },
-          "404": {
-            "description": "User not found",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
-            }
-          }
-        }
-      },
-      "delete": {
-        "tags": [
-          "users"
-        ],
-        "summary": "Delete a user and all associated data (GDPR Article 17 - Right to Erasure)",
-        "description": "Permanently deletes the user and all associated data including:\n- User record\n- Organization and project memberships\n- API keys owned by the user\n- Conversations owned by the user\n- Dynamic providers owned by the user\n- Usage records for user's API keys\n\nThis operation is irreversible.",
-        "operationId": "user_delete",
-        "parameters": [
           {
             "name": "user_id",
             "in": "path",
@@ -9676,14 +10123,7 @@
         ],
         "responses": {
           "200": {
-            "description": "User deleted",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/UserDeletionResponse"
-                }
-              }
-            }
+            "description": "Member removed"
           },
           "403": {
             "description": "Access denied",
@@ -9696,7 +10136,7 @@
             }
           },
           "404": {
-            "description": "User not found",
+            "description": "Organization, team, or membership not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -9709,11 +10149,29 @@
       },
       "patch": {
         "tags": [
-          "users"
+          "teams"
         ],
-        "summary": "Update a user",
-        "operationId": "user_update",
+        "summary": "Update a team member's role",
+        "operationId": "team_member_update",
         "parameters": [
+          {
+            "name": "org_slug",
+            "in": "path",
+            "description": "Organization slug",
+            "required": true,
+            "schema": {
+              "type": "string"
+            }
+          },
+          {
+            "name": "team_slug",
+            "in": "path",
+            "description": "Team slug",
+            "required": true,
+            "schema": {
+              "type": "string"
+            }
+          },
           {
             "name": "user_id",
             "in": "path",
@@ -9729,7 +10187,7 @@
           "content": {
             "application/json": {
               "schema": {
-                "$ref": "#/components/schemas/UpdateUser"
+                "$ref": "#/components/schemas/UpdateTeamMember"
               }
             }
           },
@@ -9737,11 +10195,11 @@
         },
         "responses": {
           "200": {
-            "description": "User updated",
+            "description": "Member role updated",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/User"
+                  "$ref": "#/components/schemas/TeamMember"
                 }
               }
             }
@@ -9757,7 +10215,7 @@
             }
           },
           "404": {
-            "description": "User not found",
+            "description": "Organization, team, or membership not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -9769,90 +10227,30 @@
         }
       }
     },
-    "/admin/v1/users/{user_id}/access-summary": {
+    "/admin/v1/organizations/{org_slug}/teams/{team_slug}/templates": {
       "get": {
         "tags": [
-          "access-reviews"
+          "templates"
         ],
-        "summary": "Get access summary for a specific user",
-        "description": "Returns a comprehensive access summary for the specified user including:\n- All organizations the user belongs to with roles and grant dates\n- All projects the user belongs to with roles and grant dates\n- All API keys owned by the user\n- Last activity timestamps per resource\n- Summary statistics\n\nUse `format=csv` for CSV export suitable for auditors and spreadsheets.",
-        "operationId": "user_access_summary",
+        "summary": "List templates by team",
+        "operationId": "template_list_by_team",
         "parameters": [
           {
-            "name": "user_id",
+            "name": "org_slug",
             "in": "path",
-            "description": "User ID",
+            "description": "Organization slug",
             "required": true,
             "schema": {
-              "type": "string",
-              "format": "uuid"
-            }
-          },
-          {
-            "name": "format",
-            "in": "query",
-            "description": "Export format (json or csv)",
-            "required": false,
-            "schema": {
-              "oneOf": [
-                {
-                  "$ref": "#/components/schemas/ExportFormat"
-                }
-              ],
-              "default": "json"
-            }
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "User access summary (JSON or CSV based on format parameter)",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/UserAccessSummaryResponse"
-                }
-              }
-            }
-          },
-          "403": {
-            "description": "Access denied",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
+              "type": "string"
             }
           },
-          "404": {
-            "description": "User not found",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
-            }
-          }
-        }
-      }
-    },
-    "/admin/v1/users/{user_id}/api-keys": {
-      "get": {
-        "tags": [
-          "api-keys"
-        ],
-        "summary": "List API keys by user",
-        "operationId": "api_key_list_by_user",
-        "parameters": [
           {
-            "name": "user_id",
+            "name": "team_slug",
             "in": "path",
-            "description": "User ID",
+            "description": "Team slug",
             "required": true,
             "schema": {
-              "type": "string",
-              "format": "uuid"
+              "type": "string"
             }
           },
           {
@@ -9907,11 +10305,11 @@
         ],
         "responses": {
           "200": {
-            "description": "List of API keys",
+            "description": "List of templates",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ApiKeyListResponse"
+                  "$ref": "#/components/schemas/TemplateListResponse"
                 }
               }
             }
@@ -9925,57 +10323,50 @@
                 }
               }
             }
+          },
+          "404": {
+            "description": "Organization or team not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
           }
         }
       }
     },
-    "/admin/v1/users/{user_id}/conversations": {
+    "/admin/v1/organizations/{org_slug}/teams/{team_slug}/usage": {
       "get": {
         "tags": [
-          "conversations"
+          "usage"
         ],
-        "summary": "List conversations by user",
-        "operationId": "conversation_list_by_user",
+        "summary": "Get usage summary for a team",
+        "operationId": "usage_get_team_summary",
         "parameters": [
           {
-            "name": "user_id",
+            "name": "org_slug",
             "in": "path",
-            "description": "User ID",
+            "description": "Organization slug",
             "required": true,
             "schema": {
-              "type": "string",
-              "format": "uuid"
+              "type": "string"
             }
           },
           {
-            "name": "limit",
-            "in": "query",
-            "description": "Maximum number of results to return",
-            "required": false,
-            "schema": {
-              "type": [
-                "integer",
-                "null"
-              ],
-              "format": "int64"
-            }
-          },
-          {
-            "name": "cursor",
-            "in": "query",
-            "description": "Cursor for keyset pagination. Encoded as base64 string.",
-            "required": false,
+            "name": "team_slug",
+            "in": "path",
+            "description": "Team slug",
+            "required": true,
             "schema": {
-              "type": [
-                "string",
-                "null"
-              ]
+              "type": "string"
             }
           },
           {
-            "name": "direction",
+            "name": "start_date",
             "in": "query",
-            "description": "Pagination direction: \"forward\" (default) or \"backward\".",
+            "description": "Start date (YYYY-MM-DD)",
             "required": false,
             "schema": {
               "type": [
@@ -9985,13 +10376,13 @@
             }
           },
           {
-            "name": "include_deleted",
+            "name": "end_date",
             "in": "query",
-            "description": "Include soft-deleted records in results",
+            "description": "End date (YYYY-MM-DD)",
             "required": false,
             "schema": {
               "type": [
-                "boolean",
+                "string",
                 "null"
               ]
             }
@@ -9999,27 +10390,17 @@
         ],
         "responses": {
           "200": {
-            "description": "List of conversations",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ConversationListResponse"
-                }
-              }
-            }
-          },
-          "400": {
-            "description": "Invalid cursor or direction",
+            "description": "Usage summary",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "$ref": "#/components/schemas/UsageSummaryResponse"
                 }
               }
             }
           },
           "404": {
-            "description": "User not found",
+            "description": "Team not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -10031,54 +10412,73 @@
         }
       }
     },
-    "/admin/v1/users/{user_id}/conversations/accessible": {
+    "/admin/v1/organizations/{org_slug}/teams/{team_slug}/usage/by-date": {
       "get": {
         "tags": [
-          "conversations"
+          "usage"
         ],
-        "summary": "List all conversations accessible to a user",
-        "description": "Returns both user's personal conversations and conversations from projects they belong to.\nResults include project metadata when applicable.",
-        "operationId": "conversation_list_accessible_for_user",
+        "summary": "Get usage by date for a team",
+        "operationId": "usage_get_team_by_date",
         "parameters": [
           {
-            "name": "user_id",
+            "name": "org_slug",
             "in": "path",
-            "description": "User ID",
+            "description": "Organization slug",
             "required": true,
             "schema": {
-              "type": "string",
-              "format": "uuid"
+              "type": "string"
             }
           },
           {
-            "name": "limit",
+            "name": "team_slug",
+            "in": "path",
+            "description": "Team slug",
+            "required": true,
+            "schema": {
+              "type": "string"
+            }
+          },
+          {
+            "name": "start_date",
             "in": "query",
-            "description": "Maximum number of conversations to return",
+            "description": "Start date (YYYY-MM-DD)",
             "required": false,
             "schema": {
               "type": [
-                "integer",
+                "string",
                 "null"
-              ],
-              "format": "int64",
-              "maximum": 1000,
-              "minimum": 1
+              ]
+            }
+          },
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
             }
           }
         ],
         "responses": {
           "200": {
-            "description": "List of accessible conversations",
+            "description": "Daily usage breakdown",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ConversationWithProjectListResponse"
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/DailySpendResponse"
+                  }
                 }
               }
             }
           },
           "404": {
-            "description": "User not found",
+            "description": "Team not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -10090,41 +10490,36 @@
         }
       }
     },
-    "/admin/v1/users/{user_id}/dynamic-providers": {
+    "/admin/v1/organizations/{org_slug}/teams/{team_slug}/usage/by-date-model": {
       "get": {
         "tags": [
-          "dynamic-providers"
+          "usage"
         ],
-        "summary": "List dynamic providers by user",
-        "operationId": "dynamic_provider_list_by_user",
+        "summary": "Get usage by date and model for a team",
+        "operationId": "usage_get_team_by_date_model",
         "parameters": [
           {
-            "name": "user_id",
+            "name": "org_slug",
             "in": "path",
-            "description": "User ID",
+            "description": "Organization slug",
             "required": true,
             "schema": {
-              "type": "string",
-              "format": "uuid"
+              "type": "string"
             }
           },
           {
-            "name": "limit",
-            "in": "query",
-            "description": "Maximum number of results to return",
-            "required": false,
+            "name": "team_slug",
+            "in": "path",
+            "description": "Team slug",
+            "required": true,
             "schema": {
-              "type": [
-                "integer",
-                "null"
-              ],
-              "format": "int64"
+              "type": "string"
             }
           },
           {
-            "name": "cursor",
+            "name": "start_date",
             "in": "query",
-            "description": "Cursor for keyset pagination. Encoded as base64 string.",
+            "description": "Start date (YYYY-MM-DD)",
             "required": false,
             "schema": {
               "type": [
@@ -10134,9 +10529,9 @@
             }
           },
           {
-            "name": "direction",
+            "name": "end_date",
             "in": "query",
-            "description": "Pagination direction: \"forward\" (default) or \"backward\".",
+            "description": "End date (YYYY-MM-DD)",
             "required": false,
             "schema": {
               "type": [
@@ -10144,37 +10539,18 @@
                 "null"
               ]
             }
-          },
-          {
-            "name": "include_deleted",
-            "in": "query",
-            "description": "Include soft-deleted records in results",
-            "required": false,
-            "schema": {
-              "type": [
-                "boolean",
-                "null"
-              ]
-            }
           }
         ],
         "responses": {
           "200": {
-            "description": "List of dynamic providers",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/DynamicProviderListResponse"
-                }
-              }
-            }
-          },
-          "400": {
-            "description": "Invalid cursor or direction",
+            "description": "Daily usage breakdown by model",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/DailyModelSpendResponse"
+                  }
                 }
               }
             }
@@ -10182,95 +10558,36 @@
         }
       }
     },
-    "/admin/v1/users/{user_id}/export": {
+    "/admin/v1/organizations/{org_slug}/teams/{team_slug}/usage/by-date-pricing-source": {
       "get": {
         "tags": [
-          "users"
+          "usage"
         ],
-        "summary": "Export all user data (GDPR Article 15 - Right of Access)",
-        "description": "Returns all personal data associated with the user including:\n- User profile\n- Organization and project memberships\n- API keys (excluding sensitive hash)\n- Conversations\n- Usage summary\n- Audit logs where user was the actor",
-        "operationId": "user_export",
+        "summary": "Get usage by date and pricing source for a team",
+        "operationId": "usage_get_team_by_date_pricing_source",
         "parameters": [
           {
-            "name": "user_id",
+            "name": "org_slug",
             "in": "path",
-            "description": "User ID",
+            "description": "Organization slug",
             "required": true,
             "schema": {
-              "type": "string",
-              "format": "uuid"
-            }
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "User data export",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/UserDataExport"
-                }
-              }
-            }
-          },
-          "403": {
-            "description": "Access denied",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
+              "type": "string"
             }
           },
-          "404": {
-            "description": "User not found",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
-            }
-          }
-        }
-      }
-    },
-    "/admin/v1/users/{user_id}/model-pricing": {
-      "get": {
-        "tags": [
-          "model-pricing"
-        ],
-        "summary": "List model pricing for a user",
-        "operationId": "model_pricing_list_by_user",
-        "parameters": [
           {
-            "name": "user_id",
+            "name": "team_slug",
             "in": "path",
-            "description": "User ID",
+            "description": "Team slug",
             "required": true,
             "schema": {
-              "type": "string",
-              "format": "uuid"
-            }
-          },
-          {
-            "name": "limit",
-            "in": "query",
-            "description": "Maximum number of results to return",
-            "required": false,
-            "schema": {
-              "type": [
-                "integer",
-                "null"
-              ],
-              "format": "int64"
+              "type": "string"
             }
           },
           {
-            "name": "cursor",
+            "name": "start_date",
             "in": "query",
-            "description": "Cursor for keyset pagination. Encoded as base64 string.",
+            "description": "Start date (YYYY-MM-DD)",
             "required": false,
             "schema": {
               "type": [
@@ -10280,9 +10597,9 @@
             }
           },
           {
-            "name": "direction",
+            "name": "end_date",
             "in": "query",
-            "description": "Pagination direction: \"forward\" (default) or \"backward\".",
+            "description": "End date (YYYY-MM-DD)",
             "required": false,
             "schema": {
               "type": [
@@ -10290,37 +10607,18 @@
                 "null"
               ]
             }
-          },
-          {
-            "name": "include_deleted",
-            "in": "query",
-            "description": "Include soft-deleted records in results",
-            "required": false,
-            "schema": {
-              "type": [
-                "boolean",
-                "null"
-              ]
-            }
           }
         ],
         "responses": {
           "200": {
-            "description": "List of user model pricing",
+            "description": "Daily usage breakdown by pricing source",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ModelPricingListResponse"
-                }
-              }
-            }
-          },
-          "400": {
-            "description": "Invalid cursor or direction",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/DailyPricingSourceSpendResponse"
+                  }
                 }
               }
             }
@@ -10328,41 +10626,36 @@
         }
       }
     },
-    "/admin/v1/users/{user_id}/prompts": {
+    "/admin/v1/organizations/{org_slug}/teams/{team_slug}/usage/by-date-project": {
       "get": {
         "tags": [
-          "prompts"
+          "usage"
         ],
-        "summary": "List prompts by user",
-        "operationId": "prompt_list_by_user",
+        "summary": "Get usage by date and project for a team",
+        "operationId": "usage_get_team_by_date_project",
         "parameters": [
           {
-            "name": "user_id",
+            "name": "org_slug",
             "in": "path",
-            "description": "User ID",
+            "description": "Organization slug",
             "required": true,
             "schema": {
-              "type": "string",
-              "format": "uuid"
+              "type": "string"
             }
           },
           {
-            "name": "limit",
-            "in": "query",
-            "description": "Maximum number of results to return",
-            "required": false,
+            "name": "team_slug",
+            "in": "path",
+            "description": "Team slug",
+            "required": true,
             "schema": {
-              "type": [
-                "integer",
-                "null"
-              ],
-              "format": "int64"
+              "type": "string"
             }
           },
           {
-            "name": "cursor",
+            "name": "start_date",
             "in": "query",
-            "description": "Cursor for keyset pagination. Encoded as base64 string.",
+            "description": "Start date (YYYY-MM-DD)",
             "required": false,
             "schema": {
               "type": [
@@ -10372,9 +10665,9 @@
             }
           },
           {
-            "name": "direction",
+            "name": "end_date",
             "in": "query",
-            "description": "Pagination direction: \"forward\" (default) or \"backward\".",
+            "description": "End date (YYYY-MM-DD)",
             "required": false,
             "schema": {
               "type": [
@@ -10382,33 +10675,24 @@
                 "null"
               ]
             }
-          },
-          {
-            "name": "include_deleted",
-            "in": "query",
-            "description": "Include soft-deleted records in results",
-            "required": false,
-            "schema": {
-              "type": [
-                "boolean",
-                "null"
-              ]
-            }
           }
         ],
         "responses": {
           "200": {
-            "description": "List of prompts",
+            "description": "Daily usage breakdown by project",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/PromptListResponse"
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/DailyProjectSpendResponse"
+                  }
                 }
               }
             }
           },
-          "400": {
-            "description": "Invalid cursor or direction",
+          "404": {
+            "description": "Team not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -10420,121 +10704,141 @@
         }
       }
     },
-    "/admin/v1/users/{user_id}/sessions": {
+    "/admin/v1/organizations/{org_slug}/teams/{team_slug}/usage/by-date-provider": {
       "get": {
         "tags": [
-          "users"
+          "usage"
         ],
-        "summary": "List all active sessions for a user.",
-        "description": "Returns an empty list if enhanced session management is not enabled.\nThe `enhanced_enabled` field indicates whether session tracking is active.",
-        "operationId": "user_sessions_list",
+        "summary": "Get usage by date and provider for a team",
+        "operationId": "usage_get_team_by_date_provider",
         "parameters": [
           {
-            "name": "user_id",
+            "name": "org_slug",
             "in": "path",
-            "description": "User ID",
+            "description": "Organization slug",
             "required": true,
             "schema": {
-              "type": "string",
-              "format": "uuid"
-            }
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "List of user sessions",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/SessionListResponse"
-                }
-              }
+              "type": "string"
             }
           },
-          "400": {
-            "description": "User has no external_id (API-only user)",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
+          {
+            "name": "team_slug",
+            "in": "path",
+            "description": "Team slug",
+            "required": true,
+            "schema": {
+              "type": "string"
             }
           },
-          "403": {
-            "description": "Access denied",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
             }
           },
-          "404": {
-            "description": "User not found",
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Daily usage breakdown by provider",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/DailyProviderSpendResponse"
+                  }
                 }
               }
             }
           }
         }
-      },
-      "delete": {
+      }
+    },
+    "/admin/v1/organizations/{org_slug}/teams/{team_slug}/usage/by-date-user": {
+      "get": {
         "tags": [
-          "users"
+          "usage"
         ],
-        "summary": "Revoke all sessions for a user (force logout).",
-        "description": "This is the critical endpoint for the \"terminated employee\" use case.\nReturns 0 sessions revoked if enhanced session management is not enabled.",
-        "operationId": "user_sessions_delete_all",
+        "summary": "Get usage by date and user for a team",
+        "operationId": "usage_get_team_by_date_user",
         "parameters": [
           {
-            "name": "user_id",
+            "name": "org_slug",
             "in": "path",
-            "description": "User ID",
+            "description": "Organization slug",
             "required": true,
             "schema": {
-              "type": "string",
-              "format": "uuid"
+              "type": "string"
             }
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "All sessions revoked",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/SessionsRevokedResponse"
-                }
-              }
+          },
+          {
+            "name": "team_slug",
+            "in": "path",
+            "description": "Team slug",
+            "required": true,
+            "schema": {
+              "type": "string"
             }
           },
-          "400": {
-            "description": "User has no external_id (API-only user)",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
             }
           },
-          "403": {
-            "description": "Access denied",
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Daily usage breakdown by user",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/DailyUserSpendResponse"
+                  }
                 }
               }
             }
           },
           "404": {
-            "description": "User not found",
+            "description": "Team not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -10546,59 +10850,73 @@
         }
       }
     },
-    "/admin/v1/users/{user_id}/sessions/{session_id}": {
-      "delete": {
+    "/admin/v1/organizations/{org_slug}/teams/{team_slug}/usage/by-model": {
+      "get": {
         "tags": [
-          "users"
+          "usage"
         ],
-        "summary": "Revoke a specific session for a user.",
-        "description": "Returns success even if the session doesn't exist (idempotent).",
-        "operationId": "user_sessions_delete_one",
+        "summary": "Get usage by model for a team",
+        "operationId": "usage_get_team_by_model",
         "parameters": [
           {
-            "name": "user_id",
+            "name": "org_slug",
             "in": "path",
-            "description": "User ID",
+            "description": "Organization slug",
             "required": true,
             "schema": {
-              "type": "string",
-              "format": "uuid"
+              "type": "string"
             }
           },
           {
-            "name": "session_id",
+            "name": "team_slug",
             "in": "path",
-            "description": "Session ID to revoke",
+            "description": "Team slug",
             "required": true,
             "schema": {
-              "type": "string",
-              "format": "uuid"
-            }
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "Session revoked",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/SessionsRevokedResponse"
-                }
-              }
+              "type": "string"
             }
           },
-          "400": {
-            "description": "User has no external_id or session doesn't belong to user",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Usage breakdown by model",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/ModelSpendResponse"
+                  }
                 }
               }
             }
           },
-          "403": {
-            "description": "Access denied",
+          "404": {
+            "description": "Team not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -10606,13 +10924,71 @@
                 }
               }
             }
+          }
+        }
+      }
+    },
+    "/admin/v1/organizations/{org_slug}/teams/{team_slug}/usage/by-pricing-source": {
+      "get": {
+        "tags": [
+          "usage"
+        ],
+        "summary": "Get usage by pricing source for a team",
+        "operationId": "usage_get_team_by_pricing_source",
+        "parameters": [
+          {
+            "name": "org_slug",
+            "in": "path",
+            "description": "Organization slug",
+            "required": true,
+            "schema": {
+              "type": "string"
+            }
           },
-          "404": {
-            "description": "User not found",
+          {
+            "name": "team_slug",
+            "in": "path",
+            "description": "Team slug",
+            "required": true,
+            "schema": {
+              "type": "string"
+            }
+          },
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Usage breakdown by pricing source",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/PricingSourceSpendResponse"
+                  }
                 }
               }
             }
@@ -10620,22 +10996,30 @@
         }
       }
     },
-    "/admin/v1/users/{user_id}/usage": {
+    "/admin/v1/organizations/{org_slug}/teams/{team_slug}/usage/by-project": {
       "get": {
         "tags": [
           "usage"
         ],
-        "summary": "Get usage summary for a user",
-        "operationId": "usage_get_user_summary",
+        "summary": "Get usage by project for a team",
+        "operationId": "usage_get_team_by_project",
         "parameters": [
           {
-            "name": "user_id",
+            "name": "org_slug",
             "in": "path",
-            "description": "User ID",
+            "description": "Organization slug",
             "required": true,
             "schema": {
-              "type": "string",
-              "format": "uuid"
+              "type": "string"
+            }
+          },
+          {
+            "name": "team_slug",
+            "in": "path",
+            "description": "Team slug",
+            "required": true,
+            "schema": {
+              "type": "string"
             }
           },
           {
@@ -10665,17 +11049,20 @@
         ],
         "responses": {
           "200": {
-            "description": "Usage summary",
+            "description": "Usage breakdown by project",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/UsageSummaryResponse"
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/ProjectSpendResponse"
+                  }
                 }
               }
             }
           },
           "404": {
-            "description": "User not found",
+            "description": "Team not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -10687,22 +11074,30 @@
         }
       }
     },
-    "/admin/v1/users/{user_id}/usage/by-date": {
+    "/admin/v1/organizations/{org_slug}/teams/{team_slug}/usage/by-provider": {
       "get": {
         "tags": [
           "usage"
         ],
-        "summary": "Get usage by date for a user",
-        "operationId": "usage_get_user_by_date",
+        "summary": "Get usage by provider for a team",
+        "operationId": "usage_get_team_by_provider",
         "parameters": [
           {
-            "name": "user_id",
+            "name": "org_slug",
             "in": "path",
-            "description": "User ID",
+            "description": "Organization slug",
             "required": true,
             "schema": {
-              "type": "string",
-              "format": "uuid"
+              "type": "string"
+            }
+          },
+          {
+            "name": "team_slug",
+            "in": "path",
+            "description": "Team slug",
+            "required": true,
+            "schema": {
+              "type": "string"
             }
           },
           {
@@ -10732,20 +11127,20 @@
         ],
         "responses": {
           "200": {
-            "description": "Daily usage breakdown",
+            "description": "Usage breakdown by provider",
             "content": {
               "application/json": {
                 "schema": {
                   "type": "array",
                   "items": {
-                    "$ref": "#/components/schemas/DailySpendResponse"
+                    "$ref": "#/components/schemas/ProviderSpendResponse"
                   }
                 }
               }
             }
           },
           "404": {
-            "description": "User not found",
+            "description": "Team not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -10757,22 +11152,30 @@
         }
       }
     },
-    "/admin/v1/users/{user_id}/usage/by-model": {
+    "/admin/v1/organizations/{org_slug}/teams/{team_slug}/usage/by-user": {
       "get": {
         "tags": [
           "usage"
         ],
-        "summary": "Get usage by model for a user",
-        "operationId": "usage_get_user_by_model",
+        "summary": "Get usage by user for a team",
+        "operationId": "usage_get_team_by_user",
         "parameters": [
           {
-            "name": "user_id",
+            "name": "org_slug",
             "in": "path",
-            "description": "User ID",
+            "description": "Organization slug",
             "required": true,
             "schema": {
-              "type": "string",
-              "format": "uuid"
+              "type": "string"
+            }
+          },
+          {
+            "name": "team_slug",
+            "in": "path",
+            "description": "Team slug",
+            "required": true,
+            "schema": {
+              "type": "string"
             }
           },
           {
@@ -10802,20 +11205,20 @@
         ],
         "responses": {
           "200": {
-            "description": "Usage breakdown by model",
+            "description": "Usage breakdown by user",
             "content": {
               "application/json": {
                 "schema": {
                   "type": "array",
                   "items": {
-                    "$ref": "#/components/schemas/ModelSpendResponse"
+                    "$ref": "#/components/schemas/UserSpendResponse"
                   }
                 }
               }
             }
           },
           "404": {
-            "description": "User not found",
+            "description": "Team not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -10827,23 +11230,30 @@
         }
       }
     },
-    "/admin/v1/users/{user_id}/usage/forecast": {
+    "/admin/v1/organizations/{org_slug}/teams/{team_slug}/usage/forecast": {
       "get": {
         "tags": [
           "usage"
         ],
-        "summary": "Get cost forecast for a user",
-        "description": "Uses historical usage data across all API keys owned by the user to predict future spending.\nReturns average daily spend, confidence intervals, and time series forecasts.",
-        "operationId": "usage_get_user_forecast",
+        "summary": "Get cost forecast for a team",
+        "operationId": "usage_get_team_forecast",
         "parameters": [
           {
-            "name": "user_id",
+            "name": "org_slug",
             "in": "path",
-            "description": "User ID",
+            "description": "Organization slug",
             "required": true,
             "schema": {
-              "type": "string",
-              "format": "uuid"
+              "type": "string"
+            }
+          },
+          {
+            "name": "team_slug",
+            "in": "path",
+            "description": "Team slug",
+            "required": true,
+            "schema": {
+              "type": "string"
             }
           },
           {
@@ -10885,7 +11295,7 @@
             }
           },
           "404": {
-            "description": "User not found",
+            "description": "Team not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -10897,333 +11307,181 @@
         }
       }
     },
-    "/api/v1/audio/speech": {
-      "post": {
+    "/admin/v1/organizations/{org_slug}/templates": {
+      "get": {
         "tags": [
-          "Audio"
+          "templates"
         ],
-        "summary": "Generate speech from text",
-        "description": "POST /v1/audio/speech",
-        "operationId": "api_v1_audio_speech",
-        "requestBody": {
-          "content": {
-            "application/json": {
-              "schema": {
-                "$ref": "#/components/schemas/CreateSpeechRequest"
-              }
+        "summary": "List templates by organization",
+        "operationId": "template_list_by_org",
+        "parameters": [
+          {
+            "name": "org_slug",
+            "in": "path",
+            "description": "Organization slug",
+            "required": true,
+            "schema": {
+              "type": "string"
             }
           },
-          "required": true
-        },
-        "responses": {
-          "200": {
-            "description": "Audio generated successfully",
-            "content": {
-              "audio/mpeg": {}
+          {
+            "name": "limit",
+            "in": "query",
+            "description": "Maximum number of results to return",
+            "required": false,
+            "schema": {
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "int64"
             }
           },
-          "400": {
-            "description": "Bad request"
+          {
+            "name": "cursor",
+            "in": "query",
+            "description": "Cursor for keyset pagination. Encoded as base64 string.",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
           },
-          "500": {
-            "description": "Internal server error"
-          }
-        },
-        "security": [
           {
-            "api_key": []
-          }
-        ]
-      }
-    },
-    "/api/v1/audio/transcriptions": {
-      "post": {
-        "tags": [
-          "Audio"
-        ],
-        "summary": "Transcribe audio to text",
-        "description": "POST /v1/audio/transcriptions",
-        "operationId": "api_v1_audio_transcriptions",
-        "requestBody": {
-          "content": {
-            "multipart/form-data": {
-              "schema": {
-                "$ref": "#/components/schemas/CreateTranscriptionRequest"
-              }
+            "name": "direction",
+            "in": "query",
+            "description": "Pagination direction: \"forward\" (default) or \"backward\".",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
             }
           },
-          "required": true
-        },
+          {
+            "name": "include_deleted",
+            "in": "query",
+            "description": "Include soft-deleted records in results",
+            "required": false,
+            "schema": {
+              "type": [
+                "boolean",
+                "null"
+              ]
+            }
+          }
+        ],
         "responses": {
           "200": {
-            "description": "Audio transcribed successfully",
+            "description": "List of templates",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/TranscriptionResponse"
+                  "$ref": "#/components/schemas/TemplateListResponse"
                 }
               }
             }
           },
           "400": {
-            "description": "Bad request"
-          },
-          "500": {
-            "description": "Internal server error"
-          }
-        },
-        "security": [
-          {
-            "api_key": []
-          }
-        ]
-      }
-    },
-    "/api/v1/audio/translations": {
-      "post": {
-        "tags": [
-          "Audio"
-        ],
-        "summary": "Translate audio to English text",
-        "description": "POST /v1/audio/translations",
-        "operationId": "api_v1_audio_translations",
-        "requestBody": {
-          "content": {
-            "multipart/form-data": {
-              "schema": {
-                "$ref": "#/components/schemas/CreateTranslationRequest"
+            "description": "Invalid cursor or direction",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
               }
             }
           },
-          "required": true
-        },
-        "responses": {
-          "200": {
-            "description": "Audio translated successfully",
+          "404": {
+            "description": "Organization not found",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/TranslationResponse"
+                  "$ref": "#/components/schemas/ErrorResponse"
                 }
               }
             }
-          },
-          "400": {
-            "description": "Bad request"
-          },
-          "500": {
-            "description": "Internal server error"
-          }
-        },
-        "security": [
-          {
-            "api_key": []
           }
-        ]
+        }
       }
     },
-    "/api/v1/chat/completions": {
-      "post": {
+    "/admin/v1/organizations/{slug}": {
+      "get": {
         "tags": [
-          "chat"
+          "organizations"
         ],
-        "summary": "Create a chat completion",
-        "description": "Creates a model response for the given chat conversation. Supports both streaming and\nnon-streaming responses. The model can be specified using provider prefixes (e.g.,\n`openai/gpt-4o`) or with dynamic routing for multi-tenant configurations.",
-        "operationId": "api_v1_chat_completions",
-        "requestBody": {
-          "content": {
-            "application/json": {
-              "schema": {
-                "$ref": "#/components/schemas/CreateChatCompletionPayload"
-              },
-              "examples": {
-                "Simple": {
-                  "summary": "Simple text completion",
-                  "value": {
-                    "messages": [
-                      {
-                        "content": "Hello, how are you?",
-                        "role": "user"
-                      }
-                    ],
-                    "model": "openai/gpt-4o"
-                  }
-                },
-                "Streaming": {
-                  "summary": "Streaming completion",
-                  "value": {
-                    "messages": [
-                      {
-                        "content": "Write a short poem about coding.",
-                        "role": "user"
-                      }
-                    ],
-                    "model": "openai/gpt-4o",
-                    "stream": true
-                  }
-                },
-                "With system prompt": {
-                  "summary": "Completion with system prompt and parameters",
-                  "value": {
-                    "max_tokens": 500,
-                    "messages": [
-                      {
-                        "content": "You are a helpful assistant.",
-                        "role": "system"
-                      },
-                      {
-                        "content": "Explain quantum computing in simple terms.",
-                        "role": "user"
-                      }
-                    ],
-                    "model": "anthropic/claude-sonnet-4-20250514",
-                    "temperature": 0.7
-                  }
-                },
-                "With tools": {
-                  "summary": "Completion with function calling",
-                  "value": {
-                    "messages": [
-                      {
-                        "content": "What's the weather in San Francisco?",
-                        "role": "user"
-                      }
-                    ],
-                    "model": "openai/gpt-4o",
-                    "tool_choice": "auto",
-                    "tools": [
-                      {
-                        "function": {
-                          "description": "Get the current weather for a location",
-                          "name": "get_weather",
-                          "parameters": {
-                            "properties": {
-                              "location": {
-                                "description": "City name",
-                                "type": "string"
-                              }
-                            },
-                            "required": [
-                              "location"
-                            ],
-                            "type": "object"
-                          }
-                        },
-                        "type": "function"
-                      }
-                    ]
-                  }
-                }
-              }
+        "summary": "Get an organization by slug",
+        "operationId": "organization_get",
+        "parameters": [
+          {
+            "name": "slug",
+            "in": "path",
+            "description": "Organization slug",
+            "required": true,
+            "schema": {
+              "type": "string"
             }
-          },
-          "required": true
-        },
+          }
+        ],
         "responses": {
           "200": {
-            "description": "Chat completion response (streaming returns SSE events)"
-          },
-          "400": {
-            "description": "Bad request - invalid model, missing fields, or validation error",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                },
-                "example": {
-                  "error": {
-                    "code": "routing_error",
-                    "message": "Model 'invalid-model' not found"
-                  }
-                }
-              }
-            }
-          },
-          "401": {
-            "description": "Unauthorized - invalid or missing API key",
+            "description": "Organization found",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                },
-                "example": {
-                  "error": {
-                    "code": "invalid_api_key",
-                    "message": "Invalid API key provided"
-                  }
+                  "$ref": "#/components/schemas/Organization"
                 }
               }
             }
           },
-          "429": {
-            "description": "Rate limit exceeded",
+          "403": {
+            "description": "Access denied",
             "content": {
               "application/json": {
                 "schema": {
                   "$ref": "#/components/schemas/ErrorResponse"
-                },
-                "example": {
-                  "error": {
-                    "code": "rate_limit_exceeded",
-                    "details": {
-                      "limit": 100,
-                      "retry_after_secs": 30,
-                      "window": "minute"
-                    },
-                    "message": "Rate limit exceeded: 100 requests per minute"
-                  }
                 }
               }
             }
           },
-          "502": {
-            "description": "Provider error - upstream LLM provider returned an error",
+          "404": {
+            "description": "Organization not found",
             "content": {
               "application/json": {
                 "schema": {
                   "$ref": "#/components/schemas/ErrorResponse"
-                },
-                "example": {
-                  "error": {
-                    "code": "provider_error",
-                    "message": "Upstream provider returned error: Service temporarily unavailable"
-                  }
                 }
               }
             }
           }
-        },
-        "security": [
-          {
-            "api_key": []
-          }
-        ]
-      }
-    },
-    "/api/v1/completions": {
-      "post": {
+        }
+      },
+      "delete": {
         "tags": [
-          "completions"
+          "organizations"
         ],
-        "summary": "Create a text completion",
-        "description": "Creates a completion for the provided prompt and parameters.",
-        "operationId": "api_v1_completions",
-        "requestBody": {
-          "content": {
-            "application/json": {
-              "schema": {
-                "$ref": "#/components/schemas/CreateCompletionPayload"
-              }
+        "summary": "Delete an organization",
+        "operationId": "organization_delete",
+        "parameters": [
+          {
+            "name": "slug",
+            "in": "path",
+            "description": "Organization slug",
+            "required": true,
+            "schema": {
+              "type": "string"
             }
-          },
-          "required": true
-        },
+          }
+        ],
         "responses": {
           "200": {
-            "description": "Completion response (streaming or non-streaming)"
+            "description": "Organization deleted"
           },
-          "400": {
-            "description": "Bad request",
+          "403": {
+            "description": "Access denied",
             "content": {
               "application/json": {
                 "schema": {
@@ -11232,8 +11490,8 @@
               }
             }
           },
-          "502": {
-            "description": "Provider error",
+          "404": {
+            "description": "Organization not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -11242,48 +11500,30 @@
               }
             }
           }
-        },
-        "security": [
+        }
+      },
+      "patch": {
+        "tags": [
+          "organizations"
+        ],
+        "summary": "Update an organization",
+        "operationId": "organization_update",
+        "parameters": [
           {
-            "api_key": []
+            "name": "slug",
+            "in": "path",
+            "description": "Organization slug",
+            "required": true,
+            "schema": {
+              "type": "string"
+            }
           }
-        ]
-      }
-    },
-    "/api/v1/embeddings": {
-      "post": {
-        "tags": [
-          "embeddings"
         ],
-        "summary": "Create embeddings",
-        "description": "Creates an embedding vector representing the input text. Embeddings are useful for\nsemantic search, clustering, classification, and similarity comparisons.",
-        "operationId": "api_v1_embeddings",
         "requestBody": {
           "content": {
             "application/json": {
               "schema": {
-                "$ref": "#/components/schemas/CreateEmbeddingPayload"
-              },
-              "examples": {
-                "Multiple texts": {
-                  "summary": "Embed multiple texts in one request",
-                  "value": {
-                    "dimensions": 1024,
-                    "input": [
-                      "First document to embed",
-                      "Second document to embed",
-                      "Third document to embed"
-                    ],
-                    "model": "openai/text-embedding-3-large"
-                  }
-                },
-                "Single text": {
-                  "summary": "Embed a single text string",
-                  "value": {
-                    "input": "Hello world",
-                    "model": "openai/text-embedding-3-small"
-                  }
-                }
+                "$ref": "#/components/schemas/UpdateOrganization"
               }
             }
           },
@@ -11291,160 +11531,162 @@
         },
         "responses": {
           "200": {
-            "description": "Embedding vectors for the input text(s)"
+            "description": "Organization updated",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/Organization"
+                }
+              }
+            }
           },
-          "400": {
-            "description": "Bad request - invalid model or input",
+          "403": {
+            "description": "Access denied",
             "content": {
               "application/json": {
                 "schema": {
                   "$ref": "#/components/schemas/ErrorResponse"
-                },
-                "example": {
-                  "error": {
-                    "code": "routing_error",
-                    "message": "Model 'invalid-embedding-model' not found"
-                  }
                 }
               }
             }
           },
-          "502": {
-            "description": "Provider error",
+          "404": {
+            "description": "Organization not found",
             "content": {
               "application/json": {
                 "schema": {
                   "$ref": "#/components/schemas/ErrorResponse"
-                },
-                "example": {
-                  "error": {
-                    "code": "provider_error",
-                    "message": "Upstream provider returned error"
-                  }
                 }
               }
             }
           }
-        },
-        "security": [
-          {
-            "api_key": []
-          }
-        ]
+        }
       }
     },
-    "/api/v1/files": {
+    "/admin/v1/organizations/{slug}/usage": {
       "get": {
         "tags": [
-          "files"
+          "usage"
         ],
-        "summary": "List files",
-        "description": "Returns a list of files owned by the specified owner.",
-        "operationId": "file_list",
+        "summary": "Get usage summary for an organization",
+        "operationId": "usage_get_org_summary",
         "parameters": [
           {
-            "name": "limit",
-            "in": "query",
-            "description": "Maximum number of files to return (default: 20, max: 100)",
-            "required": false,
+            "name": "slug",
+            "in": "path",
+            "description": "Organization slug",
+            "required": true,
             "schema": {
-              "type": [
-                "integer",
-                "null"
-              ],
-              "format": "int64",
-              "maximum": 100,
-              "minimum": 1
+              "type": "string"
             }
           },
           {
-            "name": "order",
+            "name": "start_date",
             "in": "query",
-            "description": "Sort order by `created_at` timestamp (default: desc)",
+            "description": "Start date (YYYY-MM-DD)",
             "required": false,
             "schema": {
-              "oneOf": [
-                {
-                  "type": "null"
-                },
-                {
-                  "$ref": "#/components/schemas/SortOrder"
-                }
+              "type": [
+                "string",
+                "null"
               ]
             }
           },
           {
-            "name": "after",
+            "name": "end_date",
             "in": "query",
-            "description": "Cursor for forward pagination. Returns results after this file ID.",
+            "description": "End date (YYYY-MM-DD)",
             "required": false,
             "schema": {
               "type": [
                 "string",
                 "null"
               ]
-            },
-            "example": "file-550e8400-e29b-41d4-a716-446655440000"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Usage summary",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/UsageSummaryResponse"
+                }
+              }
+            }
           },
+          "404": {
+            "description": "Organization not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/organizations/{slug}/usage/by-date": {
+      "get": {
+        "tags": [
+          "usage"
+        ],
+        "summary": "Get usage by date for an organization",
+        "operationId": "usage_get_org_by_date",
+        "parameters": [
           {
-            "name": "before",
+            "name": "slug",
+            "in": "path",
+            "description": "Organization slug",
+            "required": true,
+            "schema": {
+              "type": "string"
+            }
+          },
+          {
+            "name": "start_date",
             "in": "query",
-            "description": "**Hadrian Extension:** Cursor for backward pagination. Returns results before this file ID.",
+            "description": "Start date (YYYY-MM-DD)",
             "required": false,
             "schema": {
               "type": [
                 "string",
                 "null"
               ]
-            },
-            "example": "file-550e8400-e29b-41d4-a716-446655440000"
+            }
           },
           {
-            "name": "purpose",
+            "name": "end_date",
             "in": "query",
-            "description": "Filter by purpose",
+            "description": "End date (YYYY-MM-DD)",
             "required": false,
             "schema": {
               "type": [
                 "string",
                 "null"
               ]
-            },
-            "example": "assistants"
-          },
-          {
-            "name": "owner_type",
-            "in": "query",
-            "description": "**Hadrian Extension:** Owner type for multi-tenancy (organization, project, or user)",
-            "required": true,
-            "schema": {
-              "type": "string"
-            }
-          },
-          {
-            "name": "owner_id",
-            "in": "query",
-            "description": "**Hadrian Extension:** Owner ID for multi-tenancy",
-            "required": true,
-            "schema": {
-              "type": "string",
-              "format": "uuid"
             }
           }
         ],
         "responses": {
           "200": {
-            "description": "List of files",
+            "description": "Daily usage breakdown",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/FileListResponse"
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/DailySpendResponse"
+                  }
                 }
               }
             }
           },
-          "400": {
-            "description": "Invalid request",
+          "404": {
+            "description": "Organization not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -11453,165 +11695,185 @@
               }
             }
           }
-        },
-        "security": [
-          {
-            "api_key": []
-          }
-        ]
-      },
-      "post": {
+        }
+      }
+    },
+    "/admin/v1/organizations/{slug}/usage/by-date-model": {
+      "get": {
         "tags": [
-          "files"
+          "usage"
         ],
-        "summary": "Upload a file",
-        "description": "Uploads a file that can be used with vector stores for RAG.\nFiles are uploaded as multipart/form-data with the following fields:\n- `file`: The file to upload (required)\n- `purpose`: The intended purpose of the file (default: \"assistants\")\n- `owner_type`: Owner type - \"organization\", \"project\", or \"user\" (required)\n- `owner_id`: Owner ID (required)",
-        "operationId": "file_upload",
-        "requestBody": {
-          "description": "File upload with metadata",
-          "content": {
-            "multipart/form-data": {}
-          }
-        },
-        "responses": {
-          "200": {
-            "description": "File uploaded successfully",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/File"
-                }
-              }
+        "summary": "Get usage by date and model for an organization",
+        "operationId": "usage_get_org_by_date_model",
+        "parameters": [
+          {
+            "name": "slug",
+            "in": "path",
+            "description": "Organization slug",
+            "required": true,
+            "schema": {
+              "type": "string"
             }
           },
-          "400": {
-            "description": "Invalid request",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
             }
           },
-          "413": {
-            "description": "File too large",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
             }
-          },
-          "422": {
-            "description": "Virus detected in uploaded file",
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Daily usage breakdown by model",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/DailyModelSpendResponse"
+                  }
                 }
               }
             }
           }
-        },
-        "security": [
-          {
-            "api_key": []
-          }
-        ]
+        }
       }
     },
-    "/api/v1/files/{file_id}": {
+    "/admin/v1/organizations/{slug}/usage/by-date-pricing-source": {
       "get": {
         "tags": [
-          "files"
+          "usage"
         ],
-        "summary": "Get file metadata",
-        "description": "Returns information about a specific file.",
-        "operationId": "file_get",
+        "summary": "Get usage by date and pricing source for an organization",
+        "operationId": "usage_get_org_by_date_pricing_source",
         "parameters": [
           {
-            "name": "file_id",
+            "name": "slug",
             "in": "path",
-            "description": "File ID",
+            "description": "Organization slug",
             "required": true,
             "schema": {
-              "type": "string",
-              "format": "uuid"
+              "type": "string"
+            }
+          },
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
             }
           }
         ],
         "responses": {
           "200": {
-            "description": "File metadata",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/File"
-                }
-              }
-            }
-          },
-          "404": {
-            "description": "File not found",
+            "description": "Daily usage breakdown by pricing source",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/DailyPricingSourceSpendResponse"
+                  }
                 }
               }
             }
           }
-        },
-        "security": [
-          {
-            "api_key": []
-          }
-        ]
-      },
-      "delete": {
+        }
+      }
+    },
+    "/admin/v1/organizations/{slug}/usage/by-date-project": {
+      "get": {
         "tags": [
-          "files"
+          "usage"
         ],
-        "summary": "Delete a file",
-        "description": "Deletes a file. The file cannot be deleted if it is still referenced by any vector stores.",
-        "operationId": "file_delete",
+        "summary": "Get usage by date and project for an organization",
+        "operationId": "usage_get_org_by_date_project",
         "parameters": [
           {
-            "name": "file_id",
+            "name": "slug",
             "in": "path",
-            "description": "File ID",
+            "description": "Organization slug",
             "required": true,
             "schema": {
-              "type": "string",
-              "format": "uuid"
+              "type": "string"
+            }
+          },
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
             }
           }
         ],
         "responses": {
           "200": {
-            "description": "File deleted",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/DeleteFileResponse"
-                }
-              }
-            }
-          },
-          "400": {
-            "description": "File is still in use",
+            "description": "Daily usage breakdown by project",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/DailyProjectSpendResponse"
+                  }
                 }
               }
             }
           },
           "404": {
-            "description": "File not found",
+            "description": "Organization not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -11620,209 +11882,126 @@
               }
             }
           }
-        },
-        "security": [
-          {
-            "api_key": []
-          }
-        ]
+        }
       }
     },
-    "/api/v1/files/{file_id}/content": {
+    "/admin/v1/organizations/{slug}/usage/by-date-provider": {
       "get": {
         "tags": [
-          "files"
+          "usage"
         ],
-        "summary": "Get file content",
-        "description": "Returns the content of a file.",
-        "operationId": "file_get_content",
+        "summary": "Get usage by date and provider for an organization",
+        "operationId": "usage_get_org_by_date_provider",
         "parameters": [
           {
-            "name": "file_id",
+            "name": "slug",
             "in": "path",
-            "description": "File ID",
+            "description": "Organization slug",
             "required": true,
             "schema": {
-              "type": "string",
-              "format": "uuid"
-            }
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "File content",
-            "content": {
-              "application/octet-stream": {}
+              "type": "string"
             }
           },
-          "404": {
-            "description": "File not found",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
-            }
-          }
-        },
-        "security": [
           {
-            "api_key": []
-          }
-        ]
-      }
-    },
-    "/api/v1/images/edits": {
-      "post": {
-        "tags": [
-          "Images"
-        ],
-        "summary": "Edit image with text instructions",
-        "description": "POST /v1/images/edits",
-        "operationId": "api_v1_images_edits",
-        "requestBody": {
-          "content": {
-            "multipart/form-data": {
-              "schema": {
-                "$ref": "#/components/schemas/CreateImageEditRequest"
-              }
-            }
-          },
-          "required": true
-        },
-        "responses": {
-          "200": {
-            "description": "Image edited successfully",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ImagesResponse"
-                }
-              }
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
             }
           },
-          "400": {
-            "description": "Bad request"
-          },
-          "500": {
-            "description": "Internal server error"
-          }
-        },
-        "security": [
           {
-            "api_key": []
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
           }
-        ]
-      }
-    },
-    "/api/v1/images/generations": {
-      "post": {
-        "tags": [
-          "Images"
         ],
-        "summary": "Create image from text prompt",
-        "description": "POST /v1/images/generations",
-        "operationId": "api_v1_images_generations",
-        "requestBody": {
-          "content": {
-            "application/json": {
-              "schema": {
-                "$ref": "#/components/schemas/CreateImageRequest"
-              }
-            }
-          },
-          "required": true
-        },
         "responses": {
           "200": {
-            "description": "Image generated successfully",
+            "description": "Daily usage breakdown by provider",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ImagesResponse"
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/DailyProviderSpendResponse"
+                  }
                 }
               }
             }
-          },
-          "400": {
-            "description": "Bad request"
-          },
-          "500": {
-            "description": "Internal server error"
-          }
-        },
-        "security": [
-          {
-            "api_key": []
           }
-        ]
+        }
       }
     },
-    "/api/v1/images/variations": {
-      "post": {
+    "/admin/v1/organizations/{slug}/usage/by-date-team": {
+      "get": {
         "tags": [
-          "Images"
+          "usage"
         ],
-        "summary": "Create image variations",
-        "description": "POST /v1/images/variations",
-        "operationId": "api_v1_images_variations",
-        "requestBody": {
-          "content": {
-            "multipart/form-data": {
-              "schema": {
-                "$ref": "#/components/schemas/CreateImageVariationRequest"
-              }
+        "summary": "Get usage by date and team for an organization",
+        "operationId": "usage_get_org_by_date_team",
+        "parameters": [
+          {
+            "name": "slug",
+            "in": "path",
+            "description": "Organization slug",
+            "required": true,
+            "schema": {
+              "type": "string"
             }
           },
-          "required": true
-        },
-        "responses": {
-          "200": {
-            "description": "Image variations created successfully",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ImagesResponse"
-                }
-              }
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
             }
           },
-          "400": {
-            "description": "Bad request"
-          },
-          "500": {
-            "description": "Internal server error"
-          }
-        },
-        "security": [
           {
-            "api_key": []
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
           }
-        ]
-      }
-    },
-    "/api/v1/models": {
-      "get": {
-        "tags": [
-          "models"
         ],
-        "summary": "List available models",
-        "description": "Lists all models available from all configured providers.",
-        "operationId": "api_v1_models",
         "responses": {
           "200": {
-            "description": "List of available models",
+            "description": "Daily usage breakdown by team",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/CombinedModelsResponse"
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/DailyTeamSpendResponse"
+                  }
                 }
               }
             }
           },
-          "400": {
-            "description": "Bad request",
+          "404": {
+            "description": "Organization not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -11831,48 +12010,67 @@
               }
             }
           }
-        },
-        "security": [
-          {
-            "api_key": []
-          }
-        ]
+        }
       }
     },
-    "/api/v1/responses": {
-      "post": {
+    "/admin/v1/organizations/{slug}/usage/by-date-user": {
+      "get": {
         "tags": [
-          "chat"
+          "usage"
         ],
-        "summary": "Create a response",
-        "description": "Creates a model response using the Responses API format.",
-        "operationId": "api_v1_responses",
-        "requestBody": {
-          "content": {
-            "application/json": {
-              "schema": {
-                "$ref": "#/components/schemas/CreateResponsesPayload"
-              }
+        "summary": "Get usage by date and user for an organization",
+        "operationId": "usage_get_org_by_date_user",
+        "parameters": [
+          {
+            "name": "slug",
+            "in": "path",
+            "description": "Organization slug",
+            "required": true,
+            "schema": {
+              "type": "string"
             }
           },
-          "required": true
-        },
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        ],
         "responses": {
           "200": {
-            "description": "Response object (streaming or non-streaming)"
-          },
-          "400": {
-            "description": "Bad request",
+            "description": "Daily usage breakdown by user",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/DailyUserSpendResponse"
+                  }
                 }
               }
             }
           },
-          "502": {
-            "description": "Provider error",
+          "404": {
+            "description": "Organization not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -11881,174 +12079,195 @@
               }
             }
           }
-        },
-        "security": [
-          {
-            "api_key": []
-          }
-        ]
+        }
       }
     },
-    "/api/v1/vector_stores": {
+    "/admin/v1/organizations/{slug}/usage/by-model": {
       "get": {
         "tags": [
-          "vector-stores"
+          "usage"
         ],
-        "summary": "List vector stores",
-        "description": "Returns a list of vector stores owned by the specified owner.",
-        "operationId": "vector_store_list",
+        "summary": "Get usage by model for an organization",
+        "operationId": "usage_get_org_by_model",
         "parameters": [
           {
-            "name": "owner_type",
-            "in": "query",
-            "description": "**Hadrian Extension:** Owner type for multi-tenancy (organization, team, project, or user).\nWhen omitted along with `owner_id`, returns all accessible vector stores.",
-            "required": false,
+            "name": "slug",
+            "in": "path",
+            "description": "Organization slug",
+            "required": true,
             "schema": {
-              "type": [
-                "string",
-                "null"
-              ]
+              "type": "string"
             }
           },
           {
-            "name": "owner_id",
+            "name": "start_date",
             "in": "query",
-            "description": "**Hadrian Extension:** Owner ID for multi-tenancy.\nWhen omitted along with `owner_type`, returns all accessible vector stores.",
+            "description": "Start date (YYYY-MM-DD)",
             "required": false,
             "schema": {
               "type": [
                 "string",
                 "null"
-              ],
-              "format": "uuid"
+              ]
             }
           },
           {
-            "name": "limit",
+            "name": "end_date",
             "in": "query",
-            "description": "Maximum number of vector stores to return (default: 20, max: 100)",
+            "description": "End date (YYYY-MM-DD)",
             "required": false,
             "schema": {
               "type": [
-                "integer",
+                "string",
                 "null"
-              ],
-              "format": "int64",
-              "maximum": 100,
-              "minimum": 1
+              ]
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Usage breakdown by model",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/ModelSpendResponse"
+                  }
+                }
+              }
             }
           },
+          "404": {
+            "description": "Organization not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/organizations/{slug}/usage/by-pricing-source": {
+      "get": {
+        "tags": [
+          "usage"
+        ],
+        "summary": "Get usage by pricing source for an organization",
+        "operationId": "usage_get_org_by_pricing_source",
+        "parameters": [
           {
-            "name": "order",
-            "in": "query",
-            "description": "Sort order by `created_at` timestamp (default: desc)",
-            "required": false,
+            "name": "slug",
+            "in": "path",
+            "description": "Organization slug",
+            "required": true,
             "schema": {
-              "oneOf": [
-                {
-                  "type": "null"
-                },
-                {
-                  "$ref": "#/components/schemas/SortOrder"
-                }
-              ]
+              "type": "string"
             }
           },
           {
-            "name": "after",
+            "name": "start_date",
             "in": "query",
-            "description": "Cursor for forward pagination. Returns results after this object ID.\nUse the `last_id` from a previous response to get the next page.",
+            "description": "Start date (YYYY-MM-DD)",
             "required": false,
             "schema": {
               "type": [
                 "string",
                 "null"
               ]
-            },
-            "example": "vs_550e8400-e29b-41d4-a716-446655440000"
+            }
           },
           {
-            "name": "before",
+            "name": "end_date",
             "in": "query",
-            "description": "Cursor for backward pagination. Returns results before this object ID.\nUse the `first_id` from a previous response to get the previous page.",
+            "description": "End date (YYYY-MM-DD)",
             "required": false,
             "schema": {
               "type": [
                 "string",
                 "null"
               ]
-            },
-            "example": "vs_550e8400-e29b-41d4-a716-446655440000"
+            }
           }
         ],
         "responses": {
           "200": {
-            "description": "List of vector stores",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/VectorStoreListResponse"
-                }
-              }
-            }
-          },
-          "400": {
-            "description": "Invalid request",
+            "description": "Usage breakdown by pricing source",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/PricingSourceSpendResponse"
+                  }
                 }
               }
             }
           }
-        },
-        "security": [
-          {
-            "api_key": []
-          }
-        ]
-      },
-      "post": {
+        }
+      }
+    },
+    "/admin/v1/organizations/{slug}/usage/by-project": {
+      "get": {
         "tags": [
-          "vector-stores"
+          "usage"
         ],
-        "summary": "Create a vector store",
-        "description": "Creates a new vector store for storing file embeddings.\nOptionally attaches files to the vector store at creation time via `file_ids`.",
-        "operationId": "vector_store_create",
-        "requestBody": {
-          "content": {
-            "application/json": {
-              "schema": {
-                "$ref": "#/components/schemas/CreateVectorStore"
-              }
+        "summary": "Get usage by project for an organization",
+        "operationId": "usage_get_org_by_project",
+        "parameters": [
+          {
+            "name": "slug",
+            "in": "path",
+            "description": "Organization slug",
+            "required": true,
+            "schema": {
+              "type": "string"
             }
           },
-          "required": true
-        },
-        "responses": {
-          "201": {
-            "description": "Vector store created",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/VectorStore"
-                }
-              }
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
             }
           },
-          "400": {
-            "description": "Invalid request",
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Usage breakdown by project",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/ProjectSpendResponse"
+                  }
                 }
               }
             }
           },
           "404": {
-            "description": "Owner not found",
+            "description": "Organization not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -12057,46 +12276,67 @@
               }
             }
           }
-        },
-        "security": [
-          {
-            "api_key": []
-          }
-        ]
+        }
       }
     },
-    "/api/v1/vector_stores/{vector_store_id}": {
+    "/admin/v1/organizations/{slug}/usage/by-provider": {
       "get": {
         "tags": [
-          "vector-stores"
+          "usage"
         ],
-        "summary": "Get a vector store",
-        "description": "Retrieves a vector store by ID.",
-        "operationId": "vector_store_get",
+        "summary": "Get usage by provider for an organization",
+        "operationId": "usage_get_org_by_provider",
         "parameters": [
           {
-            "name": "vector_store_id",
+            "name": "slug",
             "in": "path",
-            "description": "Vector store ID (e.g., vs_550e8400-e29b-41d4-a716-446655440000)",
+            "description": "Organization slug",
             "required": true,
             "schema": {
               "type": "string"
             }
+          },
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
           }
         ],
         "responses": {
           "200": {
-            "description": "Vector store details",
+            "description": "Usage breakdown by provider",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/VectorStore"
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/ProviderSpendResponse"
+                  }
                 }
               }
             }
           },
           "404": {
-            "description": "Vector store not found",
+            "description": "Organization not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -12105,55 +12345,67 @@
               }
             }
           }
-        },
-        "security": [
-          {
-            "api_key": []
-          }
-        ]
-      },
-      "post": {
+        }
+      }
+    },
+    "/admin/v1/organizations/{slug}/usage/by-team": {
+      "get": {
         "tags": [
-          "vector-stores"
+          "usage"
         ],
-        "summary": "Modify a vector store",
-        "description": "Modifies a vector store's metadata.",
-        "operationId": "vector_store_modify",
+        "summary": "Get usage by team for an organization",
+        "operationId": "usage_get_org_by_team",
         "parameters": [
           {
-            "name": "vector_store_id",
+            "name": "slug",
             "in": "path",
-            "description": "Vector store ID",
+            "description": "Organization slug",
             "required": true,
             "schema": {
-              "type": "string",
-              "format": "uuid"
+              "type": "string"
             }
-          }
-        ],
-        "requestBody": {
-          "content": {
-            "application/json": {
-              "schema": {
-                "$ref": "#/components/schemas/UpdateVectorStore"
-              }
+          },
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
             }
           },
-          "required": true
-        },
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        ],
         "responses": {
           "200": {
-            "description": "Vector store updated",
+            "description": "Usage breakdown by team",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/VectorStore"
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/TeamSpendResponse"
+                  }
                 }
               }
             }
           },
           "404": {
-            "description": "Vector store not found",
+            "description": "Organization not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -12162,45 +12414,67 @@
               }
             }
           }
-        },
-        "security": [
-          {
-            "api_key": []
-          }
-        ]
-      },
-      "delete": {
+        }
+      }
+    },
+    "/admin/v1/organizations/{slug}/usage/by-user": {
+      "get": {
         "tags": [
-          "vector-stores"
+          "usage"
         ],
-        "summary": "Delete a vector store",
-        "description": "Deletes a vector store and all its files (soft delete).",
-        "operationId": "vector_store_delete",
+        "summary": "Get usage by user for an organization",
+        "operationId": "usage_get_org_by_user",
         "parameters": [
           {
-            "name": "vector_store_id",
+            "name": "slug",
             "in": "path",
-            "description": "Vector store ID",
+            "description": "Organization slug",
             "required": true,
             "schema": {
-              "type": "string",
-              "format": "uuid"
+              "type": "string"
+            }
+          },
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
             }
           }
         ],
         "responses": {
           "200": {
-            "description": "Vector store deleted",
+            "description": "Usage breakdown by user",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/DeleteVectorStoreResponse"
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/UserSpendResponse"
+                  }
                 }
               }
             }
           },
           "404": {
-            "description": "Vector store not found",
+            "description": "Organization not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -12209,57 +12483,67 @@
               }
             }
           }
-        },
-        "security": [
-          {
-            "api_key": []
-          }
-        ]
+        }
       }
     },
-    "/api/v1/vector_stores/{vector_store_id}/file_batches": {
-      "post": {
+    "/admin/v1/organizations/{slug}/usage/forecast": {
+      "get": {
         "tags": [
-          "vector-stores"
+          "usage"
         ],
-        "summary": "Create a file batch",
-        "description": "Creates a batch of files to be added to a vector store.\nNote: File batches are not yet fully implemented. This endpoint creates\nfiles individually and returns a batch representation.\n\n## Content Deduplication\n\nFiles are deduplicated by content hash (SHA-256). If a file with identical content\nalready exists in the vector store, it is counted as \"completed\" in the batch\nresponse but no re-processing occurs. This prevents duplicate chunks and wasted\ncompute while still reporting success for the file.\n\nThe `file_counts.completed` field in the response includes both newly processed\nfiles and deduplicated files.\n\n## Embedding Model Validation\n\nThe gateway validates that its configured embedding model matches the vector store's\nembedding model before processing any files in the batch. This prevents incompatible\nembeddings from being stored together. If there's a mismatch, a 409 Conflict error\nis returned with details about the expected vs. configured models.",
-        "operationId": "vector_store_file_batch_create",
+        "summary": "Get cost forecast for an organization",
+        "description": "Uses historical usage data across all API keys in the organization to predict future spending.\nReturns average daily spend, confidence intervals, and time series forecasts.",
+        "operationId": "usage_get_org_forecast",
         "parameters": [
           {
-            "name": "vector_store_id",
+            "name": "slug",
             "in": "path",
-            "description": "Vector store ID",
+            "description": "Organization slug",
             "required": true,
             "schema": {
-              "type": "string",
-              "format": "uuid"
+              "type": "string"
             }
-          }
-        ],
-        "requestBody": {
-          "content": {
-            "application/json": {
-              "schema": {
-                "$ref": "#/components/schemas/CreateFileBatchRequest"
-              }
+          },
+          {
+            "name": "lookback_days",
+            "in": "query",
+            "description": "Number of days of historical data to use (default: 30)",
+            "required": false,
+            "schema": {
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "int32"
             }
           },
-          "required": true
-        },
+          {
+            "name": "forecast_days",
+            "in": "query",
+            "description": "Number of days to forecast ahead (default: 7)",
+            "required": false,
+            "schema": {
+              "type": [
+                "integer",
+                "null"
+              ],
+              "minimum": 0
+            }
+          }
+        ],
         "responses": {
-          "201": {
-            "description": "File batch created",
+          "200": {
+            "description": "Cost forecast",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/FileBatch"
+                  "$ref": "#/components/schemas/CostForecastResponse"
                 }
               }
             }
           },
-          "400": {
-            "description": "Invalid request",
+          "404": {
+            "description": "Organization not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -12267,68 +12551,92 @@
                 }
               }
             }
-          },
-          "404": {
-            "description": "Vector store not found",
+          }
+        }
+      }
+    },
+    "/admin/v1/providers/circuit-breakers": {
+      "get": {
+        "tags": [
+          "providers"
+        ],
+        "summary": "Get circuit breaker status for all providers.",
+        "description": "Returns the current state and failure count for all configured\ncircuit breakers. Useful for monitoring provider health.",
+        "operationId": "list_circuit_breakers",
+        "responses": {
+          "200": {
+            "description": "Circuit breaker status for all providers",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "$ref": "#/components/schemas/CircuitBreakersResponse"
                 }
               }
             }
-          },
-          "409": {
-            "description": "Embedding model mismatch",
+          }
+        }
+      }
+    },
+    "/admin/v1/providers/health": {
+      "get": {
+        "tags": [
+          "providers"
+        ],
+        "summary": "Get health status for all providers.",
+        "description": "Returns the current health status for all providers that have health checks\nenabled. Includes status, latency, last check time, and consecutive\nsuccess/failure counts.\n\nNote: Only providers with `health_check.enabled = true` in their config\nwill appear in this list. Providers without health checks rely solely\non circuit breaker status.",
+        "operationId": "list_provider_health",
+        "responses": {
+          "200": {
+            "description": "Health status for all providers",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "$ref": "#/components/schemas/ProviderHealthResponse"
                 }
               }
             }
-          },
-          "503": {
-            "description": "File search service not configured",
+          }
+        }
+      }
+    },
+    "/admin/v1/providers/stats": {
+      "get": {
+        "tags": [
+          "providers"
+        ],
+        "summary": "Get aggregated statistics for all providers.",
+        "description": "Returns current metrics including latency percentiles, error counts,\ntoken usage, and costs for all providers.\n\nIn single-node deployments, stats are derived from the local /metrics endpoint.\nIn multi-node deployments with Prometheus configured, stats are aggregated\nfrom Prometheus queries.",
+        "operationId": "list_provider_stats",
+        "responses": {
+          "200": {
+            "description": "Stats for all providers",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "$ref": "#/components/schemas/ProviderStatsResponse"
                 }
               }
             }
+          },
+          "500": {
+            "description": "Failed to fetch stats"
           }
-        },
-        "security": [
-          {
-            "api_key": []
-          }
-        ]
+        }
       }
     },
-    "/api/v1/vector_stores/{vector_store_id}/file_batches/{batch_id}": {
+    "/admin/v1/providers/{provider_name}/circuit-breaker": {
       "get": {
         "tags": [
-          "vector-stores"
+          "providers"
         ],
-        "summary": "Get a file batch",
-        "description": "Retrieves a file batch. Note: File batches are executed synchronously,\nso this endpoint returns a \"completed\" or \"failed\" status.",
-        "operationId": "vector_store_file_batch_get",
+        "summary": "Get circuit breaker status for a specific provider.",
+        "description": "Returns the current state and failure count for the specified provider's\ncircuit breaker.",
+        "operationId": "get_circuit_breaker",
         "parameters": [
           {
-            "name": "vector_store_id",
-            "in": "path",
-            "description": "Vector store ID",
-            "required": true,
-            "schema": {
-              "type": "string",
-              "format": "uuid"
-            }
-          },
-          {
-            "name": "batch_id",
+            "name": "provider_name",
             "in": "path",
-            "description": "File batch ID",
+            "description": "Provider name",
             "required": true,
             "schema": {
               "type": "string"
@@ -12336,45 +12644,35 @@
           }
         ],
         "responses": {
-          "404": {
-            "description": "File batches are not persisted",
+          "200": {
+            "description": "Circuit breaker status for the provider",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "$ref": "#/components/schemas/ProviderCircuitBreakerResponse"
                 }
               }
             }
+          },
+          "404": {
+            "description": "Provider not found or circuit breaker not enabled"
           }
-        },
-        "security": [
-          {
-            "api_key": []
-          }
-        ]
-      },
-      "delete": {
+        }
+      }
+    },
+    "/admin/v1/providers/{provider_name}/health": {
+      "get": {
         "tags": [
-          "vector-stores"
+          "providers"
         ],
-        "summary": "Cancel a file batch",
-        "description": "Cancels a file batch. Note: File batches are executed synchronously,\nso cancellation is not supported.",
-        "operationId": "vector_store_file_batch_cancel",
+        "summary": "Get health status for a specific provider.",
+        "description": "Returns the current health status for the specified provider. Only works\nfor providers that have health checks enabled.",
+        "operationId": "get_provider_health",
         "parameters": [
           {
-            "name": "vector_store_id",
-            "in": "path",
-            "description": "Vector store ID",
-            "required": true,
-            "schema": {
-              "type": "string",
-              "format": "uuid"
-            }
-          },
-          {
-            "name": "batch_id",
+            "name": "provider_name",
             "in": "path",
-            "description": "File batch ID",
+            "description": "Provider name",
             "required": true,
             "schema": {
               "type": "string"
@@ -12382,47 +12680,35 @@
           }
         ],
         "responses": {
-          "400": {
-            "description": "File batches cannot be cancelled",
+          "200": {
+            "description": "Health status for the provider",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "$ref": "#/components/schemas/ProviderHealthState"
                 }
               }
             }
+          },
+          "404": {
+            "description": "Provider not found or health checks not enabled"
           }
-        },
-        "security": [
-          {
-            "api_key": []
-          }
-        ]
+        }
       }
     },
-    "/api/v1/vector_stores/{vector_store_id}/file_batches/{batch_id}/files": {
+    "/admin/v1/providers/{provider_name}/stats": {
       "get": {
         "tags": [
-          "vector-stores"
+          "providers"
         ],
-        "summary": "List files in a batch",
-        "description": "Lists files in a file batch. Note: File batches are not persisted.",
-        "operationId": "vector_store_file_batch_list_files",
+        "summary": "Get aggregated statistics for a specific provider.",
+        "description": "Returns current metrics including latency percentiles, error counts,\ntoken usage, and costs for the specified provider.",
+        "operationId": "get_provider_stats",
         "parameters": [
           {
-            "name": "vector_store_id",
-            "in": "path",
-            "description": "Vector store ID",
-            "required": true,
-            "schema": {
-              "type": "string",
-              "format": "uuid"
-            }
-          },
-          {
-            "name": "batch_id",
+            "name": "provider_name",
             "in": "path",
-            "description": "File batch ID",
+            "description": "Provider name",
             "required": true,
             "schema": {
               "type": "string"
@@ -12430,104 +12716,129 @@
           }
         ],
         "responses": {
-          "404": {
-            "description": "File batches are not persisted",
+          "200": {
+            "description": "Stats for the provider",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "$ref": "#/components/schemas/ProviderStats"
                 }
               }
             }
+          },
+          "404": {
+            "description": "Provider not found or no stats available"
           }
-        },
-        "security": [
-          {
-            "api_key": []
-          }
-        ]
+        }
       }
     },
-    "/api/v1/vector_stores/{vector_store_id}/files": {
+    "/admin/v1/providers/{provider_name}/stats/history": {
       "get": {
         "tags": [
-          "vector-stores"
+          "providers"
         ],
-        "summary": "List vector store files",
-        "description": "Returns a list of files in a vector store.",
-        "operationId": "vector_store_file_list",
+        "summary": "Get historical statistics for a specific provider.",
+        "description": "Returns time series data for the specified provider within the given\ntime range. Data is returned as hourly or daily buckets depending\non the granularity parameter.\n\n**Note:** Historical stats require Prometheus to be configured via\n`observability.metrics.prometheus_query_url`. In single-node deployments\nwithout Prometheus, this endpoint returns an error.",
+        "operationId": "get_provider_stats_history",
         "parameters": [
           {
-            "name": "vector_store_id",
+            "name": "provider_name",
             "in": "path",
-            "description": "Vector store ID",
+            "description": "Provider name",
             "required": true,
             "schema": {
-              "type": "string",
-              "format": "uuid"
+              "type": "string"
             }
           },
           {
-            "name": "limit",
+            "name": "start",
             "in": "query",
-            "description": "Maximum number of files to return (default: 20, max: 100)",
+            "description": "Start of the time range (defaults to 24 hours ago).",
             "required": false,
             "schema": {
               "type": [
-                "integer",
+                "string",
                 "null"
               ],
-              "format": "int64",
-              "maximum": 100,
-              "minimum": 1
+              "format": "date-time"
             }
           },
           {
-            "name": "order",
+            "name": "end",
             "in": "query",
-            "description": "Sort order by `created_at` timestamp (default: desc)",
+            "description": "End of the time range (defaults to now).",
             "required": false,
             "schema": {
-              "oneOf": [
-                {
-                  "type": "null"
-                },
-                {
-                  "$ref": "#/components/schemas/SortOrder"
-                }
-              ]
+              "type": [
+                "string",
+                "null"
+              ],
+              "format": "date-time"
             }
           },
           {
-            "name": "after",
+            "name": "granularity",
             "in": "query",
-            "description": "Cursor for forward pagination. Returns results after this file ID.",
+            "description": "Granularity of the data points: \"hour\" or \"day\" (defaults to \"hour\").",
             "required": false,
             "schema": {
               "type": [
                 "string",
                 "null"
               ]
-            },
-            "example": "vsf_550e8400-e29b-41d4-a716-446655440000"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Historical stats for the provider",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ProviderStatsHistorical"
+                }
+              }
+            }
+          },
+          "400": {
+            "description": "Invalid query parameters or Prometheus not configured"
+          }
+        }
+      }
+    },
+    "/admin/v1/providers/{provider}/usage": {
+      "get": {
+        "tags": [
+          "usage"
+        ],
+        "summary": "Get usage summary for a provider",
+        "operationId": "usage_get_provider_summary",
+        "parameters": [
+          {
+            "name": "provider",
+            "in": "path",
+            "description": "Provider name",
+            "required": true,
+            "schema": {
+              "type": "string"
+            }
           },
           {
-            "name": "before",
+            "name": "start_date",
             "in": "query",
-            "description": "Cursor for backward pagination. Returns results before this file ID.",
+            "description": "Start date (YYYY-MM-DD)",
             "required": false,
             "schema": {
               "type": [
                 "string",
                 "null"
               ]
-            },
-            "example": "vsf_550e8400-e29b-41d4-a716-446655440000"
+            }
           },
           {
-            "name": "filter",
+            "name": "end_date",
             "in": "query",
-            "description": "Filter by status (in_progress, completed, failed, cancelled)",
+            "description": "End date (YYYY-MM-DD)",
             "required": false,
             "schema": {
               "type": [
@@ -12539,94 +12850,226 @@
         ],
         "responses": {
           "200": {
-            "description": "List of files",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/VectorStoreFileListResponse"
-                }
-              }
-            }
-          },
-          "404": {
-            "description": "Vector store not found",
+            "description": "Usage summary",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "$ref": "#/components/schemas/UsageSummaryResponse"
                 }
               }
             }
           }
-        },
-        "security": [
-          {
-            "api_key": []
-          }
-        ]
-      },
-      "post": {
+        }
+      }
+    },
+    "/admin/v1/providers/{provider}/usage/by-date": {
+      "get": {
         "tags": [
-          "vector-stores"
+          "usage"
         ],
-        "summary": "Create a vector store file",
-        "description": "Adds a file to a vector store. The file must already exist in the Files API.\nProcessing will start automatically after the file is added.\n\n## Content Deduplication\n\nFiles are deduplicated by content hash (SHA-256). If a file with identical content\nalready exists in the vector store, the existing file is returned with status 200\ninstead of creating a duplicate. This is idempotent behavior—uploading the same\ncontent multiple times has no additional effect.\n\n## Embedding Model Validation\n\nThe gateway validates that its configured embedding model matches the vector store's\nembedding model before adding files. This prevents incompatible embeddings from being\nstored together. If there's a mismatch, a 409 Conflict error is returned with details\nabout the expected vs. configured models.\n\n- **201 Created**: New file added, processing started\n- **200 OK**: Duplicate content detected, existing file returned (no re-processing)\n- **409 Conflict**: Embedding model mismatch between gateway configuration and vector store",
-        "operationId": "vector_store_file_create",
+        "summary": "Get usage by date for a provider",
+        "operationId": "usage_get_provider_by_date",
         "parameters": [
           {
-            "name": "vector_store_id",
+            "name": "provider",
             "in": "path",
-            "description": "Vector store ID",
+            "description": "Provider name",
             "required": true,
             "schema": {
-              "type": "string",
-              "format": "uuid"
+              "type": "string"
+            }
+          },
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
             }
           }
         ],
-        "requestBody": {
-          "content": {
-            "application/json": {
-              "schema": {
-                "$ref": "#/components/schemas/CreateVectorStoreFileRequest"
+        "responses": {
+          "200": {
+            "description": "Daily usage breakdown",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/DailySpendResponse"
+                  }
+                }
               }
             }
+          }
+        }
+      }
+    },
+    "/admin/v1/providers/{provider}/usage/by-model": {
+      "get": {
+        "tags": [
+          "usage"
+        ],
+        "summary": "Get usage by model for a provider",
+        "operationId": "usage_get_provider_by_model",
+        "parameters": [
+          {
+            "name": "provider",
+            "in": "path",
+            "description": "Provider name",
+            "required": true,
+            "schema": {
+              "type": "string"
+            }
           },
-          "required": true
-        },
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        ],
         "responses": {
           "200": {
-            "description": "Duplicate content detected, existing file returned",
+            "description": "Usage breakdown by model",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/VectorStoreFile"
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/ModelSpendResponse"
+                  }
                 }
               }
             }
+          }
+        }
+      }
+    },
+    "/admin/v1/providers/{provider}/usage/forecast": {
+      "get": {
+        "tags": [
+          "usage"
+        ],
+        "summary": "Get cost forecast for a provider",
+        "description": "Uses historical usage data across all API keys using this provider to predict future spending.\nReturns average daily spend, confidence intervals, and time series forecasts.",
+        "operationId": "usage_get_provider_forecast",
+        "parameters": [
+          {
+            "name": "provider",
+            "in": "path",
+            "description": "Provider name",
+            "required": true,
+            "schema": {
+              "type": "string"
+            }
           },
-          "201": {
-            "description": "File added to vector store",
+          {
+            "name": "lookback_days",
+            "in": "query",
+            "description": "Number of days of historical data to use (default: 30)",
+            "required": false,
+            "schema": {
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "int32"
+            }
+          },
+          {
+            "name": "forecast_days",
+            "in": "query",
+            "description": "Number of days to forecast ahead (default: 7)",
+            "required": false,
+            "schema": {
+              "type": [
+                "integer",
+                "null"
+              ],
+              "minimum": 0
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Cost forecast",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/VectorStoreFile"
+                  "$ref": "#/components/schemas/CostForecastResponse"
                 }
               }
             }
+          }
+        }
+      }
+    },
+    "/admin/v1/rbac-policies/validate": {
+      "post": {
+        "tags": [
+          "rbac-policies"
+        ],
+        "summary": "Validate a CEL expression",
+        "description": "Checks if a CEL expression is syntactically valid without creating a policy.\nUseful for validating expressions before saving.",
+        "operationId": "org_rbac_policy_validate",
+        "requestBody": {
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/ValidateCelRequest"
+              }
+            }
           },
-          "400": {
-            "description": "Invalid request",
+          "required": true
+        },
+        "responses": {
+          "200": {
+            "description": "Validation result",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "$ref": "#/components/schemas/ValidateCelResponse"
                 }
               }
             }
           },
-          "404": {
-            "description": "Vector store or file not found",
+          "403": {
+            "description": "Access denied",
             "content": {
               "application/json": {
                 "schema": {
@@ -12634,19 +13077,31 @@
                 }
               }
             }
-          },
-          "409": {
-            "description": "Embedding model mismatch",
+          }
+        }
+      }
+    },
+    "/admin/v1/session-info": {
+      "get": {
+        "tags": [
+          "session"
+        ],
+        "summary": "Get comprehensive session and access information.",
+        "description": "Returns detailed information about the current user's authentication state,\ndatabase profile, organization/team/project memberships, and SSO configuration.\nUseful for debugging authentication and authorization issues.",
+        "operationId": "session_info_get",
+        "responses": {
+          "200": {
+            "description": "Session information",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "$ref": "#/components/schemas/SessionInfoResponse"
                 }
               }
             }
           },
-          "503": {
-            "description": "File search service not configured",
+          "401": {
+            "description": "Not authenticated",
             "content": {
               "application/json": {
                 "schema": {
@@ -12655,57 +13110,30 @@
               }
             }
           }
-        },
-        "security": [
-          {
-            "api_key": []
-          }
-        ]
+        }
       }
     },
-    "/api/v1/vector_stores/{vector_store_id}/files/{file_id}": {
+    "/admin/v1/sso-connections": {
       "get": {
         "tags": [
-          "vector-stores"
-        ],
-        "summary": "Get a vector store file",
-        "description": "Retrieves a file from a vector store.",
-        "operationId": "vector_store_file_get",
-        "parameters": [
-          {
-            "name": "vector_store_id",
-            "in": "path",
-            "description": "Vector store ID",
-            "required": true,
-            "schema": {
-              "type": "string",
-              "format": "uuid"
-            }
-          },
-          {
-            "name": "file_id",
-            "in": "path",
-            "description": "Vector store file ID",
-            "required": true,
-            "schema": {
-              "type": "string",
-              "format": "uuid"
-            }
-          }
+          "sso"
         ],
+        "summary": "List configured SSO connections",
+        "description": "Returns read-only information about SSO connections configured in the gateway.\nSSO connections are defined in the config file (hadrian.toml), not the database.\nCurrently only one OIDC connection is supported per deployment.",
+        "operationId": "sso_connections_list",
         "responses": {
           "200": {
-            "description": "Vector store file details",
+            "description": "List of SSO connections",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/VectorStoreFile"
+                  "$ref": "#/components/schemas/SsoConnectionsResponse"
                 }
               }
             }
           },
-          "404": {
-            "description": "Vector store or file not found",
+          "403": {
+            "description": "Access denied",
             "content": {
               "application/json": {
                 "schema": {
@@ -12714,55 +13142,50 @@
               }
             }
           }
-        },
-        "security": [
-          {
-            "api_key": []
-          }
-        ]
-      },
-      "delete": {
+        }
+      }
+    },
+    "/admin/v1/sso-connections/{name}": {
+      "get": {
         "tags": [
-          "vector-stores"
+          "sso"
         ],
-        "summary": "Delete a vector store file",
-        "description": "Removes a file from a vector store. This does not delete the underlying file\nfrom the Files API.",
-        "operationId": "vector_store_file_delete",
+        "summary": "Get a specific SSO connection by name",
+        "operationId": "sso_connection_get",
         "parameters": [
           {
-            "name": "vector_store_id",
-            "in": "path",
-            "description": "Vector store ID",
-            "required": true,
-            "schema": {
-              "type": "string",
-              "format": "uuid"
-            }
-          },
-          {
-            "name": "file_id",
+            "name": "name",
             "in": "path",
-            "description": "Vector store file ID",
+            "description": "SSO connection name",
             "required": true,
             "schema": {
-              "type": "string",
-              "format": "uuid"
+              "type": "string"
             }
           }
         ],
         "responses": {
           "200": {
-            "description": "File removed from vector store",
+            "description": "SSO connection found",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/DeleteVectorStoreFileResponse"
+                  "$ref": "#/components/schemas/SsoConnection"
+                }
+              }
+            }
+          },
+          "403": {
+            "description": "Access denied",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
                 }
               }
             }
           },
           "404": {
-            "description": "Vector store or file not found",
+            "description": "SSO connection not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -12771,37 +13194,72 @@
               }
             }
           }
+        }
+      }
+    },
+    "/admin/v1/templates": {
+      "post": {
+        "tags": [
+          "templates"
+        ],
+        "summary": "Create a template",
+        "operationId": "template_create",
+        "requestBody": {
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/CreateTemplate"
+              }
+            }
+          },
+          "required": true
         },
-        "security": [
-          {
-            "api_key": []
+        "responses": {
+          "201": {
+            "description": "Template created",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/Template"
+                }
+              }
+            }
+          },
+          "404": {
+            "description": "Owner not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "409": {
+            "description": "Template with this name already exists",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
           }
-        ]
+        }
       }
     },
-    "/api/v1/vector_stores/{vector_store_id}/files/{file_id}/chunks": {
+    "/admin/v1/templates/{id}": {
       "get": {
         "tags": [
-          "vector-stores"
+          "templates"
         ],
-        "summary": "List chunks for a file [Hadrian Extension]",
-        "description": "**Hadrian Extension** - This endpoint is not part of the standard OpenAI API.\n\nReturns all chunks that have been extracted and embedded from a file. Useful for debugging chunking behavior and verifying embeddings.",
-        "operationId": "vector_store_file_chunks_list",
+        "summary": "Get a template by ID",
+        "operationId": "template_get",
         "parameters": [
           {
-            "name": "vector_store_id",
-            "in": "path",
-            "description": "Vector store ID",
-            "required": true,
-            "schema": {
-              "type": "string",
-              "format": "uuid"
-            }
-          },
-          {
-            "name": "file_id",
+            "name": "id",
             "in": "path",
-            "description": "Vector store file ID",
+            "description": "Template ID",
             "required": true,
             "schema": {
               "type": "string",
@@ -12811,17 +13269,17 @@
         ],
         "responses": {
           "200": {
-            "description": "List of chunks for the file",
+            "description": "Template found",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ChunkListResponse"
+                  "$ref": "#/components/schemas/Template"
                 }
               }
             }
           },
           "404": {
-            "description": "Vector store or file not found",
+            "description": "Template not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -12829,9 +13287,33 @@
                 }
               }
             }
+          }
+        }
+      },
+      "delete": {
+        "tags": [
+          "templates"
+        ],
+        "summary": "Delete a template",
+        "operationId": "template_delete",
+        "parameters": [
+          {
+            "name": "id",
+            "in": "path",
+            "description": "Template ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Template deleted"
           },
-          "503": {
-            "description": "File search not configured",
+          "404": {
+            "description": "Template not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -12840,27 +13322,19 @@
               }
             }
           }
-        },
-        "security": [
-          {
-            "api_key": []
-          }
-        ]
-      }
-    },
-    "/api/v1/vector_stores/{vector_store_id}/search": {
-      "post": {
+        }
+      },
+      "patch": {
         "tags": [
-          "vector-stores"
+          "templates"
         ],
-        "summary": "Search vector store",
-        "description": "Performs a semantic search against a vector store.\n\n**Hadrian Extensions:** The response schema includes additional fields not in the standard OpenAI API:\n- `chunk_id`, `vector_store_id`, `chunk_index` (debugging info)",
-        "operationId": "vector_store_search",
+        "summary": "Update a template",
+        "operationId": "template_update",
         "parameters": [
           {
-            "name": "vector_store_id",
+            "name": "id",
             "in": "path",
-            "description": "Vector store ID",
+            "description": "Template ID",
             "required": true,
             "schema": {
               "type": "string",
@@ -12872,7 +13346,7 @@
           "content": {
             "application/json": {
               "schema": {
-                "$ref": "#/components/schemas/VectorStoreSearchRequest"
+                "$ref": "#/components/schemas/UpdateTemplate"
               }
             }
           },
@@ -12880,27 +13354,17 @@
         },
         "responses": {
           "200": {
-            "description": "Search results",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/VectorStoreSearchResponse"
-                }
-              }
-            }
-          },
-          "400": {
-            "description": "Invalid request",
+            "description": "Template updated",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
+                  "$ref": "#/components/schemas/Template"
                 }
               }
             }
           },
           "404": {
-            "description": "Vector store not found",
+            "description": "Template not found",
             "content": {
               "application/json": {
                 "schema": {
@@ -12909,8 +13373,8 @@
               }
             }
           },
-          "503": {
-            "description": "File search not configured",
+          "409": {
+            "description": "Template with this name already exists",
             "content": {
               "application/json": {
                 "schema": {
@@ -12919,39 +13383,49 @@
               }
             }
           }
-        },
-        "security": [
-          {
-            "api_key": []
-          }
-        ]
+        }
       }
     },
-    "/health": {
+    "/admin/v1/usage": {
       "get": {
         "tags": [
-          "health"
+          "usage"
         ],
-        "summary": "Full health check with subsystem status.",
-        "description": "Returns detailed status of all subsystems including database, cache, and secrets manager.\nUse this endpoint for comprehensive health monitoring and dashboards.",
-        "operationId": "health_check",
-        "responses": {
-          "200": {
-            "description": "Service is healthy",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/HealthStatus"
-                }
-              }
+        "summary": "Get global usage summary",
+        "operationId": "usage_get_global_summary",
+        "parameters": [
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
             }
           },
-          "503": {
-            "description": "Service is unhealthy",
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Global usage summary",
             "content": {
               "application/json": {
                 "schema": {
-                  "$ref": "#/components/schemas/HealthStatus"
+                  "$ref": "#/components/schemas/UsageSummaryResponse"
                 }
               }
             }
@@ -12959,34 +13433,5019 @@
         }
       }
     },
-    "/health/live": {
-      "get": {
-        "tags": [
-          "health"
-        ],
-        "summary": "Kubernetes liveness probe.",
-        "description": "Returns 200 if the service is running. This endpoint should always succeed\nunless the service process is completely broken. Use this for Kubernetes\nliveness probes to detect and restart unhealthy pods.",
-        "operationId": "health_liveness",
-        "responses": {
-          "200": {
-            "description": "Service is alive"
-          }
-        }
-      }
-    },
-    "/health/ready": {
+    "/admin/v1/usage/by-date": {
       "get": {
         "tags": [
-          "health"
+          "usage"
         ],
-        "summary": "Kubernetes readiness probe.",
-        "description": "Returns 200 if the service is ready to accept traffic. Checks that critical\ndependencies (database) are available. Use this for Kubernetes readiness\nprobes to control traffic routing to pods.",
-        "operationId": "health_readiness",
-        "responses": {
-          "200": {
-            "description": "Service is ready to accept traffic"
-          },
-          "503": {
+        "summary": "Get global usage by date",
+        "operationId": "usage_get_global_by_date",
+        "parameters": [
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Daily usage breakdown",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/DailySpendResponse"
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/usage/by-date-model": {
+      "get": {
+        "tags": [
+          "usage"
+        ],
+        "summary": "Get global usage by date and model",
+        "operationId": "usage_get_global_by_date_model",
+        "parameters": [
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Daily usage breakdown by model",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/DailyModelSpendResponse"
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/usage/by-date-org": {
+      "get": {
+        "tags": [
+          "usage"
+        ],
+        "summary": "Get global usage by date and organization",
+        "operationId": "usage_get_global_by_date_org",
+        "parameters": [
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Daily usage breakdown by organization",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/DailyOrgSpendResponse"
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/usage/by-date-pricing-source": {
+      "get": {
+        "tags": [
+          "usage"
+        ],
+        "summary": "Get global usage by date and pricing source",
+        "operationId": "usage_get_global_by_date_pricing_source",
+        "parameters": [
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Daily usage breakdown by pricing source",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/DailyPricingSourceSpendResponse"
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/usage/by-date-project": {
+      "get": {
+        "tags": [
+          "usage"
+        ],
+        "summary": "Get global usage by date and project",
+        "operationId": "usage_get_global_by_date_project",
+        "parameters": [
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Daily usage breakdown by project",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/DailyProjectSpendResponse"
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/usage/by-date-provider": {
+      "get": {
+        "tags": [
+          "usage"
+        ],
+        "summary": "Get global usage by date and provider",
+        "operationId": "usage_get_global_by_date_provider",
+        "parameters": [
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Daily usage breakdown by provider",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/DailyProviderSpendResponse"
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/usage/by-date-team": {
+      "get": {
+        "tags": [
+          "usage"
+        ],
+        "summary": "Get global usage by date and team",
+        "operationId": "usage_get_global_by_date_team",
+        "parameters": [
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Daily usage breakdown by team",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/DailyTeamSpendResponse"
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/usage/by-date-user": {
+      "get": {
+        "tags": [
+          "usage"
+        ],
+        "summary": "Get global usage by date and user",
+        "operationId": "usage_get_global_by_date_user",
+        "parameters": [
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Daily usage breakdown by user",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/DailyUserSpendResponse"
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/usage/by-model": {
+      "get": {
+        "tags": [
+          "usage"
+        ],
+        "summary": "Get global usage by model",
+        "operationId": "usage_get_global_by_model",
+        "parameters": [
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Usage breakdown by model",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/ModelSpendResponse"
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/usage/by-org": {
+      "get": {
+        "tags": [
+          "usage"
+        ],
+        "summary": "Get global usage by organization",
+        "operationId": "usage_get_global_by_org",
+        "parameters": [
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Usage breakdown by organization",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/OrgSpendResponse"
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/usage/by-pricing-source": {
+      "get": {
+        "tags": [
+          "usage"
+        ],
+        "summary": "Get global usage by pricing source",
+        "operationId": "usage_get_global_by_pricing_source",
+        "parameters": [
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Usage breakdown by pricing source",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/PricingSourceSpendResponse"
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/usage/by-project": {
+      "get": {
+        "tags": [
+          "usage"
+        ],
+        "summary": "Get global usage by project",
+        "operationId": "usage_get_global_by_project",
+        "parameters": [
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Usage breakdown by project",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/ProjectSpendResponse"
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/usage/by-provider": {
+      "get": {
+        "tags": [
+          "usage"
+        ],
+        "summary": "Get global usage by provider",
+        "operationId": "usage_get_global_by_provider",
+        "parameters": [
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Usage breakdown by provider",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/ProviderSpendResponse"
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/usage/by-team": {
+      "get": {
+        "tags": [
+          "usage"
+        ],
+        "summary": "Get global usage by team",
+        "operationId": "usage_get_global_by_team",
+        "parameters": [
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Usage breakdown by team",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/TeamSpendResponse"
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/usage/by-user": {
+      "get": {
+        "tags": [
+          "usage"
+        ],
+        "summary": "Get global usage by user",
+        "operationId": "usage_get_global_by_user",
+        "parameters": [
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Usage breakdown by user",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/UserSpendResponse"
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/usage/logs": {
+      "get": {
+        "tags": [
+          "usage"
+        ],
+        "summary": "List usage logs (admin global)",
+        "operationId": "usage_log_list",
+        "parameters": [
+          {
+            "name": "org_id",
+            "in": "query",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ],
+              "format": "uuid"
+            }
+          },
+          {
+            "name": "user_id",
+            "in": "query",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ],
+              "format": "uuid"
+            }
+          },
+          {
+            "name": "project_id",
+            "in": "query",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ],
+              "format": "uuid"
+            }
+          },
+          {
+            "name": "team_id",
+            "in": "query",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ],
+              "format": "uuid"
+            }
+          },
+          {
+            "name": "api_key_id",
+            "in": "query",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ],
+              "format": "uuid"
+            }
+          },
+          {
+            "name": "service_account_id",
+            "in": "query",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ],
+              "format": "uuid"
+            }
+          },
+          {
+            "name": "model",
+            "in": "query",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "provider",
+            "in": "query",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "provider_source",
+            "in": "query",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "from",
+            "in": "query",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ],
+              "format": "date-time"
+            }
+          },
+          {
+            "name": "to",
+            "in": "query",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ],
+              "format": "date-time"
+            }
+          },
+          {
+            "name": "limit",
+            "in": "query",
+            "required": false,
+            "schema": {
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "int64"
+            }
+          },
+          {
+            "name": "cursor",
+            "in": "query",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "direction",
+            "in": "query",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "List of usage log records",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/UsageLogListResponse"
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/usage/logs/export": {
+      "get": {
+        "tags": [
+          "usage"
+        ],
+        "summary": "Export usage logs (admin global)",
+        "operationId": "usage_log_export",
+        "parameters": [
+          {
+            "name": "org_id",
+            "in": "query",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ],
+              "format": "uuid"
+            }
+          },
+          {
+            "name": "user_id",
+            "in": "query",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ],
+              "format": "uuid"
+            }
+          },
+          {
+            "name": "project_id",
+            "in": "query",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ],
+              "format": "uuid"
+            }
+          },
+          {
+            "name": "team_id",
+            "in": "query",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ],
+              "format": "uuid"
+            }
+          },
+          {
+            "name": "api_key_id",
+            "in": "query",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ],
+              "format": "uuid"
+            }
+          },
+          {
+            "name": "service_account_id",
+            "in": "query",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ],
+              "format": "uuid"
+            }
+          },
+          {
+            "name": "model",
+            "in": "query",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "provider",
+            "in": "query",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "provider_source",
+            "in": "query",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "from",
+            "in": "query",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ],
+              "format": "date-time"
+            }
+          },
+          {
+            "name": "to",
+            "in": "query",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ],
+              "format": "date-time"
+            }
+          },
+          {
+            "name": "format",
+            "in": "query",
+            "required": false,
+            "schema": {
+              "$ref": "#/components/schemas/UsageLogExportFormat"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Exported usage logs",
+            "content": {
+              "application/x-ndjson": {}
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/users": {
+      "get": {
+        "tags": [
+          "users"
+        ],
+        "summary": "List all users",
+        "operationId": "user_list",
+        "parameters": [
+          {
+            "name": "limit",
+            "in": "query",
+            "description": "Maximum number of results to return",
+            "required": false,
+            "schema": {
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "int64"
+            }
+          },
+          {
+            "name": "cursor",
+            "in": "query",
+            "description": "Cursor for keyset pagination. Encoded as base64 string.",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "direction",
+            "in": "query",
+            "description": "Pagination direction: \"forward\" (default) or \"backward\".",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "include_deleted",
+            "in": "query",
+            "description": "Include soft-deleted records in results",
+            "required": false,
+            "schema": {
+              "type": [
+                "boolean",
+                "null"
+              ]
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "List of users",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/UserListResponse"
+                }
+              }
+            }
+          },
+          "400": {
+            "description": "Invalid cursor or direction",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "403": {
+            "description": "Access denied",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        }
+      },
+      "post": {
+        "tags": [
+          "users"
+        ],
+        "summary": "Create a user",
+        "operationId": "user_create",
+        "requestBody": {
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/CreateUser"
+              }
+            }
+          },
+          "required": true
+        },
+        "responses": {
+          "201": {
+            "description": "User created",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/User"
+                }
+              }
+            }
+          },
+          "403": {
+            "description": "Access denied",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "409": {
+            "description": "Conflict (external_id already exists)",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/users/{user_id}": {
+      "get": {
+        "tags": [
+          "users"
+        ],
+        "summary": "Get a user by ID",
+        "operationId": "user_get",
+        "parameters": [
+          {
+            "name": "user_id",
+            "in": "path",
+            "description": "User ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "User found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/User"
+                }
+              }
+            }
+          },
+          "403": {
+            "description": "Access denied",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "404": {
+            "description": "User not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        }
+      },
+      "delete": {
+        "tags": [
+          "users"
+        ],
+        "summary": "Delete a user and all associated data (GDPR Article 17 - Right to Erasure)",
+        "description": "Permanently deletes the user and all associated data including:\n- User record\n- Organization and project memberships\n- API keys owned by the user\n- Conversations owned by the user\n- Dynamic providers owned by the user\n- Usage records for user's API keys\n\nThis operation is irreversible.",
+        "operationId": "user_delete",
+        "parameters": [
+          {
+            "name": "user_id",
+            "in": "path",
+            "description": "User ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "User deleted",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/UserDeletionResponse"
+                }
+              }
+            }
+          },
+          "403": {
+            "description": "Access denied",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "404": {
+            "description": "User not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        }
+      },
+      "patch": {
+        "tags": [
+          "users"
+        ],
+        "summary": "Update a user",
+        "operationId": "user_update",
+        "parameters": [
+          {
+            "name": "user_id",
+            "in": "path",
+            "description": "User ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          }
+        ],
+        "requestBody": {
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/UpdateUser"
+              }
+            }
+          },
+          "required": true
+        },
+        "responses": {
+          "200": {
+            "description": "User updated",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/User"
+                }
+              }
+            }
+          },
+          "403": {
+            "description": "Access denied",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "404": {
+            "description": "User not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/users/{user_id}/access-summary": {
+      "get": {
+        "tags": [
+          "access-reviews"
+        ],
+        "summary": "Get access summary for a specific user",
+        "description": "Returns a comprehensive access summary for the specified user including:\n- All organizations the user belongs to with roles and grant dates\n- All projects the user belongs to with roles and grant dates\n- All API keys owned by the user\n- Last activity timestamps per resource\n- Summary statistics\n\nUse `format=csv` for CSV export suitable for auditors and spreadsheets.",
+        "operationId": "user_access_summary",
+        "parameters": [
+          {
+            "name": "user_id",
+            "in": "path",
+            "description": "User ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          },
+          {
+            "name": "format",
+            "in": "query",
+            "description": "Export format (json or csv)",
+            "required": false,
+            "schema": {
+              "oneOf": [
+                {
+                  "$ref": "#/components/schemas/ExportFormat"
+                }
+              ],
+              "default": "json"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "User access summary (JSON or CSV based on format parameter)",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/UserAccessSummaryResponse"
+                }
+              }
+            }
+          },
+          "403": {
+            "description": "Access denied",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "404": {
+            "description": "User not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/users/{user_id}/api-keys": {
+      "get": {
+        "tags": [
+          "api-keys"
+        ],
+        "summary": "List API keys by user",
+        "operationId": "api_key_list_by_user",
+        "parameters": [
+          {
+            "name": "user_id",
+            "in": "path",
+            "description": "User ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          },
+          {
+            "name": "limit",
+            "in": "query",
+            "description": "Maximum number of results to return",
+            "required": false,
+            "schema": {
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "int64"
+            }
+          },
+          {
+            "name": "cursor",
+            "in": "query",
+            "description": "Cursor for keyset pagination. Encoded as base64 string.",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "direction",
+            "in": "query",
+            "description": "Pagination direction: \"forward\" (default) or \"backward\".",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "include_deleted",
+            "in": "query",
+            "description": "Include soft-deleted records in results",
+            "required": false,
+            "schema": {
+              "type": [
+                "boolean",
+                "null"
+              ]
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "List of API keys",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ApiKeyListResponse"
+                }
+              }
+            }
+          },
+          "400": {
+            "description": "Invalid cursor or direction",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/users/{user_id}/conversations": {
+      "get": {
+        "tags": [
+          "conversations"
+        ],
+        "summary": "List conversations by user",
+        "operationId": "conversation_list_by_user",
+        "parameters": [
+          {
+            "name": "user_id",
+            "in": "path",
+            "description": "User ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          },
+          {
+            "name": "limit",
+            "in": "query",
+            "description": "Maximum number of results to return",
+            "required": false,
+            "schema": {
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "int64"
+            }
+          },
+          {
+            "name": "cursor",
+            "in": "query",
+            "description": "Cursor for keyset pagination. Encoded as base64 string.",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "direction",
+            "in": "query",
+            "description": "Pagination direction: \"forward\" (default) or \"backward\".",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "include_deleted",
+            "in": "query",
+            "description": "Include soft-deleted records in results",
+            "required": false,
+            "schema": {
+              "type": [
+                "boolean",
+                "null"
+              ]
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "List of conversations",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ConversationListResponse"
+                }
+              }
+            }
+          },
+          "400": {
+            "description": "Invalid cursor or direction",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "404": {
+            "description": "User not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/users/{user_id}/conversations/accessible": {
+      "get": {
+        "tags": [
+          "conversations"
+        ],
+        "summary": "List all conversations accessible to a user",
+        "description": "Returns both user's personal conversations and conversations from projects they belong to.\nResults include project metadata when applicable.",
+        "operationId": "conversation_list_accessible_for_user",
+        "parameters": [
+          {
+            "name": "user_id",
+            "in": "path",
+            "description": "User ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          },
+          {
+            "name": "limit",
+            "in": "query",
+            "description": "Maximum number of conversations to return",
+            "required": false,
+            "schema": {
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "int64",
+              "maximum": 1000,
+              "minimum": 1
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "List of accessible conversations",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ConversationWithProjectListResponse"
+                }
+              }
+            }
+          },
+          "404": {
+            "description": "User not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/users/{user_id}/dynamic-providers": {
+      "get": {
+        "tags": [
+          "dynamic-providers"
+        ],
+        "summary": "List dynamic providers by user",
+        "operationId": "dynamic_provider_list_by_user",
+        "parameters": [
+          {
+            "name": "user_id",
+            "in": "path",
+            "description": "User ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          },
+          {
+            "name": "limit",
+            "in": "query",
+            "description": "Maximum number of results to return",
+            "required": false,
+            "schema": {
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "int64"
+            }
+          },
+          {
+            "name": "cursor",
+            "in": "query",
+            "description": "Cursor for keyset pagination. Encoded as base64 string.",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "direction",
+            "in": "query",
+            "description": "Pagination direction: \"forward\" (default) or \"backward\".",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "include_deleted",
+            "in": "query",
+            "description": "Include soft-deleted records in results",
+            "required": false,
+            "schema": {
+              "type": [
+                "boolean",
+                "null"
+              ]
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "List of dynamic providers",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/DynamicProviderListResponse"
+                }
+              }
+            }
+          },
+          "400": {
+            "description": "Invalid cursor or direction",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/users/{user_id}/export": {
+      "get": {
+        "tags": [
+          "users"
+        ],
+        "summary": "Export all user data (GDPR Article 15 - Right of Access)",
+        "description": "Returns all personal data associated with the user including:\n- User profile\n- Organization and project memberships\n- API keys (excluding sensitive hash)\n- Conversations\n- Usage summary\n- Audit logs where user was the actor",
+        "operationId": "user_export",
+        "parameters": [
+          {
+            "name": "user_id",
+            "in": "path",
+            "description": "User ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "User data export",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/UserDataExport"
+                }
+              }
+            }
+          },
+          "403": {
+            "description": "Access denied",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "404": {
+            "description": "User not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/users/{user_id}/model-pricing": {
+      "get": {
+        "tags": [
+          "model-pricing"
+        ],
+        "summary": "List model pricing for a user",
+        "operationId": "model_pricing_list_by_user",
+        "parameters": [
+          {
+            "name": "user_id",
+            "in": "path",
+            "description": "User ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          },
+          {
+            "name": "limit",
+            "in": "query",
+            "description": "Maximum number of results to return",
+            "required": false,
+            "schema": {
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "int64"
+            }
+          },
+          {
+            "name": "cursor",
+            "in": "query",
+            "description": "Cursor for keyset pagination. Encoded as base64 string.",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "direction",
+            "in": "query",
+            "description": "Pagination direction: \"forward\" (default) or \"backward\".",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "include_deleted",
+            "in": "query",
+            "description": "Include soft-deleted records in results",
+            "required": false,
+            "schema": {
+              "type": [
+                "boolean",
+                "null"
+              ]
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "List of user model pricing",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ModelPricingListResponse"
+                }
+              }
+            }
+          },
+          "400": {
+            "description": "Invalid cursor or direction",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/users/{user_id}/sessions": {
+      "get": {
+        "tags": [
+          "users"
+        ],
+        "summary": "List all active sessions for a user.",
+        "description": "Returns an empty list if enhanced session management is not enabled.\nThe `enhanced_enabled` field indicates whether session tracking is active.",
+        "operationId": "user_sessions_list",
+        "parameters": [
+          {
+            "name": "user_id",
+            "in": "path",
+            "description": "User ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "List of user sessions",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/SessionListResponse"
+                }
+              }
+            }
+          },
+          "400": {
+            "description": "User has no external_id (API-only user)",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "403": {
+            "description": "Access denied",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "404": {
+            "description": "User not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        }
+      },
+      "delete": {
+        "tags": [
+          "users"
+        ],
+        "summary": "Revoke all sessions for a user (force logout).",
+        "description": "This is the critical endpoint for the \"terminated employee\" use case.\nReturns 0 sessions revoked if enhanced session management is not enabled.",
+        "operationId": "user_sessions_delete_all",
+        "parameters": [
+          {
+            "name": "user_id",
+            "in": "path",
+            "description": "User ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "All sessions revoked",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/SessionsRevokedResponse"
+                }
+              }
+            }
+          },
+          "400": {
+            "description": "User has no external_id (API-only user)",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "403": {
+            "description": "Access denied",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "404": {
+            "description": "User not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/users/{user_id}/sessions/{session_id}": {
+      "delete": {
+        "tags": [
+          "users"
+        ],
+        "summary": "Revoke a specific session for a user.",
+        "description": "Returns success even if the session doesn't exist (idempotent).",
+        "operationId": "user_sessions_delete_one",
+        "parameters": [
+          {
+            "name": "user_id",
+            "in": "path",
+            "description": "User ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          },
+          {
+            "name": "session_id",
+            "in": "path",
+            "description": "Session ID to revoke",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Session revoked",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/SessionsRevokedResponse"
+                }
+              }
+            }
+          },
+          "400": {
+            "description": "User has no external_id or session doesn't belong to user",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "403": {
+            "description": "Access denied",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "404": {
+            "description": "User not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/users/{user_id}/templates": {
+      "get": {
+        "tags": [
+          "templates"
+        ],
+        "summary": "List templates by user",
+        "operationId": "template_list_by_user",
+        "parameters": [
+          {
+            "name": "user_id",
+            "in": "path",
+            "description": "User ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          },
+          {
+            "name": "limit",
+            "in": "query",
+            "description": "Maximum number of results to return",
+            "required": false,
+            "schema": {
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "int64"
+            }
+          },
+          {
+            "name": "cursor",
+            "in": "query",
+            "description": "Cursor for keyset pagination. Encoded as base64 string.",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "direction",
+            "in": "query",
+            "description": "Pagination direction: \"forward\" (default) or \"backward\".",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "include_deleted",
+            "in": "query",
+            "description": "Include soft-deleted records in results",
+            "required": false,
+            "schema": {
+              "type": [
+                "boolean",
+                "null"
+              ]
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "List of templates",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/TemplateListResponse"
+                }
+              }
+            }
+          },
+          "400": {
+            "description": "Invalid cursor or direction",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/users/{user_id}/usage": {
+      "get": {
+        "tags": [
+          "usage"
+        ],
+        "summary": "Get usage summary for a user",
+        "operationId": "usage_get_user_summary",
+        "parameters": [
+          {
+            "name": "user_id",
+            "in": "path",
+            "description": "User ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          },
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Usage summary",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/UsageSummaryResponse"
+                }
+              }
+            }
+          },
+          "404": {
+            "description": "User not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/users/{user_id}/usage/by-date": {
+      "get": {
+        "tags": [
+          "usage"
+        ],
+        "summary": "Get usage by date for a user",
+        "operationId": "usage_get_user_by_date",
+        "parameters": [
+          {
+            "name": "user_id",
+            "in": "path",
+            "description": "User ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          },
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Daily usage breakdown",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/DailySpendResponse"
+                  }
+                }
+              }
+            }
+          },
+          "404": {
+            "description": "User not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/users/{user_id}/usage/by-date-model": {
+      "get": {
+        "tags": [
+          "usage"
+        ],
+        "summary": "Get usage by date and model for a user",
+        "operationId": "usage_get_user_by_date_model",
+        "parameters": [
+          {
+            "name": "user_id",
+            "in": "path",
+            "description": "User ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          },
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Daily usage breakdown by model",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/DailyModelSpendResponse"
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/users/{user_id}/usage/by-date-pricing-source": {
+      "get": {
+        "tags": [
+          "usage"
+        ],
+        "summary": "Get usage by date and pricing source for a user",
+        "operationId": "usage_get_user_by_date_pricing_source",
+        "parameters": [
+          {
+            "name": "user_id",
+            "in": "path",
+            "description": "User ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          },
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Daily usage breakdown by pricing source",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/DailyPricingSourceSpendResponse"
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/users/{user_id}/usage/by-date-provider": {
+      "get": {
+        "tags": [
+          "usage"
+        ],
+        "summary": "Get usage by date and provider for a user",
+        "operationId": "usage_get_user_by_date_provider",
+        "parameters": [
+          {
+            "name": "user_id",
+            "in": "path",
+            "description": "User ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          },
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Daily usage breakdown by provider",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/DailyProviderSpendResponse"
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/users/{user_id}/usage/by-model": {
+      "get": {
+        "tags": [
+          "usage"
+        ],
+        "summary": "Get usage by model for a user",
+        "operationId": "usage_get_user_by_model",
+        "parameters": [
+          {
+            "name": "user_id",
+            "in": "path",
+            "description": "User ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          },
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Usage breakdown by model",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/ModelSpendResponse"
+                  }
+                }
+              }
+            }
+          },
+          "404": {
+            "description": "User not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/users/{user_id}/usage/by-pricing-source": {
+      "get": {
+        "tags": [
+          "usage"
+        ],
+        "summary": "Get usage by pricing source for a user",
+        "operationId": "usage_get_user_by_pricing_source",
+        "parameters": [
+          {
+            "name": "user_id",
+            "in": "path",
+            "description": "User ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          },
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Usage breakdown by pricing source",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/PricingSourceSpendResponse"
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/users/{user_id}/usage/by-provider": {
+      "get": {
+        "tags": [
+          "usage"
+        ],
+        "summary": "Get usage by provider for a user",
+        "operationId": "usage_get_user_by_provider",
+        "parameters": [
+          {
+            "name": "user_id",
+            "in": "path",
+            "description": "User ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          },
+          {
+            "name": "start_date",
+            "in": "query",
+            "description": "Start date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "end_date",
+            "in": "query",
+            "description": "End date (YYYY-MM-DD)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Usage breakdown by provider",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/ProviderSpendResponse"
+                  }
+                }
+              }
+            }
+          },
+          "404": {
+            "description": "User not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/admin/v1/users/{user_id}/usage/forecast": {
+      "get": {
+        "tags": [
+          "usage"
+        ],
+        "summary": "Get cost forecast for a user",
+        "description": "Uses historical usage data across all API keys owned by the user to predict future spending.\nReturns average daily spend, confidence intervals, and time series forecasts.",
+        "operationId": "usage_get_user_forecast",
+        "parameters": [
+          {
+            "name": "user_id",
+            "in": "path",
+            "description": "User ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          },
+          {
+            "name": "lookback_days",
+            "in": "query",
+            "description": "Number of days of historical data to use (default: 30)",
+            "required": false,
+            "schema": {
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "int32"
+            }
+          },
+          {
+            "name": "forecast_days",
+            "in": "query",
+            "description": "Number of days to forecast ahead (default: 7)",
+            "required": false,
+            "schema": {
+              "type": [
+                "integer",
+                "null"
+              ],
+              "minimum": 0
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Cost forecast",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/CostForecastResponse"
+                }
+              }
+            }
+          },
+          "404": {
+            "description": "User not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/api/v1/audio/speech": {
+      "post": {
+        "tags": [
+          "Audio"
+        ],
+        "summary": "Generate speech from text",
+        "description": "POST /v1/audio/speech",
+        "operationId": "api_v1_audio_speech",
+        "requestBody": {
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/CreateSpeechRequest"
+              }
+            }
+          },
+          "required": true
+        },
+        "responses": {
+          "200": {
+            "description": "Audio generated successfully",
+            "content": {
+              "audio/mpeg": {}
+            }
+          },
+          "400": {
+            "description": "Bad request"
+          },
+          "500": {
+            "description": "Internal server error"
+          }
+        },
+        "security": [
+          {
+            "api_key": []
+          }
+        ]
+      }
+    },
+    "/api/v1/audio/transcriptions": {
+      "post": {
+        "tags": [
+          "Audio"
+        ],
+        "summary": "Transcribe audio to text",
+        "description": "POST /v1/audio/transcriptions",
+        "operationId": "api_v1_audio_transcriptions",
+        "requestBody": {
+          "content": {
+            "multipart/form-data": {
+              "schema": {
+                "$ref": "#/components/schemas/CreateTranscriptionRequest"
+              }
+            }
+          },
+          "required": true
+        },
+        "responses": {
+          "200": {
+            "description": "Audio transcribed successfully",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/TranscriptionResponse"
+                }
+              }
+            }
+          },
+          "400": {
+            "description": "Bad request"
+          },
+          "500": {
+            "description": "Internal server error"
+          }
+        },
+        "security": [
+          {
+            "api_key": []
+          }
+        ]
+      }
+    },
+    "/api/v1/audio/translations": {
+      "post": {
+        "tags": [
+          "Audio"
+        ],
+        "summary": "Translate audio to English text",
+        "description": "POST /v1/audio/translations",
+        "operationId": "api_v1_audio_translations",
+        "requestBody": {
+          "content": {
+            "multipart/form-data": {
+              "schema": {
+                "$ref": "#/components/schemas/CreateTranslationRequest"
+              }
+            }
+          },
+          "required": true
+        },
+        "responses": {
+          "200": {
+            "description": "Audio translated successfully",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/TranslationResponse"
+                }
+              }
+            }
+          },
+          "400": {
+            "description": "Bad request"
+          },
+          "500": {
+            "description": "Internal server error"
+          }
+        },
+        "security": [
+          {
+            "api_key": []
+          }
+        ]
+      }
+    },
+    "/api/v1/chat/completions": {
+      "post": {
+        "tags": [
+          "chat"
+        ],
+        "summary": "Create a chat completion",
+        "description": "Creates a model response for the given chat conversation. Supports both streaming and\nnon-streaming responses. The model can be specified using provider prefixes (e.g.,\n`openai/gpt-4o`) or with dynamic routing for multi-tenant configurations.",
+        "operationId": "api_v1_chat_completions",
+        "requestBody": {
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/CreateChatCompletionPayload"
+              },
+              "examples": {
+                "Simple": {
+                  "summary": "Simple text completion",
+                  "value": {
+                    "messages": [
+                      {
+                        "content": "Hello, how are you?",
+                        "role": "user"
+                      }
+                    ],
+                    "model": "openai/gpt-4o"
+                  }
+                },
+                "Streaming": {
+                  "summary": "Streaming completion",
+                  "value": {
+                    "messages": [
+                      {
+                        "content": "Write a short poem about coding.",
+                        "role": "user"
+                      }
+                    ],
+                    "model": "openai/gpt-4o",
+                    "stream": true
+                  }
+                },
+                "With system prompt": {
+                  "summary": "Completion with system prompt and parameters",
+                  "value": {
+                    "max_tokens": 500,
+                    "messages": [
+                      {
+                        "content": "You are a helpful assistant.",
+                        "role": "system"
+                      },
+                      {
+                        "content": "Explain quantum computing in simple terms.",
+                        "role": "user"
+                      }
+                    ],
+                    "model": "anthropic/claude-sonnet-4-20250514",
+                    "temperature": 0.7
+                  }
+                },
+                "With tools": {
+                  "summary": "Completion with function calling",
+                  "value": {
+                    "messages": [
+                      {
+                        "content": "What's the weather in San Francisco?",
+                        "role": "user"
+                      }
+                    ],
+                    "model": "openai/gpt-4o",
+                    "tool_choice": "auto",
+                    "tools": [
+                      {
+                        "function": {
+                          "description": "Get the current weather for a location",
+                          "name": "get_weather",
+                          "parameters": {
+                            "properties": {
+                              "location": {
+                                "description": "City name",
+                                "type": "string"
+                              }
+                            },
+                            "required": [
+                              "location"
+                            ],
+                            "type": "object"
+                          }
+                        },
+                        "type": "function"
+                      }
+                    ]
+                  }
+                }
+              }
+            }
+          },
+          "required": true
+        },
+        "responses": {
+          "200": {
+            "description": "Chat completion response (streaming returns SSE events)"
+          },
+          "400": {
+            "description": "Bad request - invalid model, missing fields, or validation error",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                },
+                "example": {
+                  "error": {
+                    "code": "routing_error",
+                    "message": "Model 'invalid-model' not found"
+                  }
+                }
+              }
+            }
+          },
+          "401": {
+            "description": "Unauthorized - invalid or missing API key",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                },
+                "example": {
+                  "error": {
+                    "code": "invalid_api_key",
+                    "message": "Invalid API key provided"
+                  }
+                }
+              }
+            }
+          },
+          "429": {
+            "description": "Rate limit exceeded",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                },
+                "example": {
+                  "error": {
+                    "code": "rate_limit_exceeded",
+                    "details": {
+                      "limit": 100,
+                      "retry_after_secs": 30,
+                      "window": "minute"
+                    },
+                    "message": "Rate limit exceeded: 100 requests per minute"
+                  }
+                }
+              }
+            }
+          },
+          "502": {
+            "description": "Provider error - upstream LLM provider returned an error",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                },
+                "example": {
+                  "error": {
+                    "code": "provider_error",
+                    "message": "Upstream provider returned error: Service temporarily unavailable"
+                  }
+                }
+              }
+            }
+          }
+        },
+        "security": [
+          {
+            "api_key": []
+          }
+        ]
+      }
+    },
+    "/api/v1/completions": {
+      "post": {
+        "tags": [
+          "completions"
+        ],
+        "summary": "Create a text completion",
+        "description": "Creates a completion for the provided prompt and parameters.",
+        "operationId": "api_v1_completions",
+        "requestBody": {
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/CreateCompletionPayload"
+              }
+            }
+          },
+          "required": true
+        },
+        "responses": {
+          "200": {
+            "description": "Completion response (streaming or non-streaming)"
+          },
+          "400": {
+            "description": "Bad request",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "502": {
+            "description": "Provider error",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        },
+        "security": [
+          {
+            "api_key": []
+          }
+        ]
+      }
+    },
+    "/api/v1/embeddings": {
+      "post": {
+        "tags": [
+          "embeddings"
+        ],
+        "summary": "Create embeddings",
+        "description": "Creates an embedding vector representing the input text. Embeddings are useful for\nsemantic search, clustering, classification, and similarity comparisons.",
+        "operationId": "api_v1_embeddings",
+        "requestBody": {
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/CreateEmbeddingPayload"
+              },
+              "examples": {
+                "Multiple texts": {
+                  "summary": "Embed multiple texts in one request",
+                  "value": {
+                    "dimensions": 1024,
+                    "input": [
+                      "First document to embed",
+                      "Second document to embed",
+                      "Third document to embed"
+                    ],
+                    "model": "openai/text-embedding-3-large"
+                  }
+                },
+                "Single text": {
+                  "summary": "Embed a single text string",
+                  "value": {
+                    "input": "Hello world",
+                    "model": "openai/text-embedding-3-small"
+                  }
+                }
+              }
+            }
+          },
+          "required": true
+        },
+        "responses": {
+          "200": {
+            "description": "Embedding vectors for the input text(s)"
+          },
+          "400": {
+            "description": "Bad request - invalid model or input",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                },
+                "example": {
+                  "error": {
+                    "code": "routing_error",
+                    "message": "Model 'invalid-embedding-model' not found"
+                  }
+                }
+              }
+            }
+          },
+          "502": {
+            "description": "Provider error",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                },
+                "example": {
+                  "error": {
+                    "code": "provider_error",
+                    "message": "Upstream provider returned error"
+                  }
+                }
+              }
+            }
+          }
+        },
+        "security": [
+          {
+            "api_key": []
+          }
+        ]
+      }
+    },
+    "/api/v1/files": {
+      "get": {
+        "tags": [
+          "files"
+        ],
+        "summary": "List files",
+        "description": "Returns a list of files owned by the specified owner.",
+        "operationId": "file_list",
+        "parameters": [
+          {
+            "name": "limit",
+            "in": "query",
+            "description": "Maximum number of files to return (default: 20, max: 100)",
+            "required": false,
+            "schema": {
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "int64",
+              "maximum": 100,
+              "minimum": 1
+            }
+          },
+          {
+            "name": "order",
+            "in": "query",
+            "description": "Sort order by `created_at` timestamp (default: desc)",
+            "required": false,
+            "schema": {
+              "oneOf": [
+                {
+                  "type": "null"
+                },
+                {
+                  "$ref": "#/components/schemas/SortOrder"
+                }
+              ]
+            }
+          },
+          {
+            "name": "after",
+            "in": "query",
+            "description": "Cursor for forward pagination. Returns results after this file ID.",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "example": "file-550e8400-e29b-41d4-a716-446655440000"
+          },
+          {
+            "name": "before",
+            "in": "query",
+            "description": "**Hadrian Extension:** Cursor for backward pagination. Returns results before this file ID.",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "example": "file-550e8400-e29b-41d4-a716-446655440000"
+          },
+          {
+            "name": "purpose",
+            "in": "query",
+            "description": "Filter by purpose",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "example": "assistants"
+          },
+          {
+            "name": "owner_type",
+            "in": "query",
+            "description": "**Hadrian Extension:** Owner type for multi-tenancy (organization, project, or user)",
+            "required": true,
+            "schema": {
+              "type": "string"
+            }
+          },
+          {
+            "name": "owner_id",
+            "in": "query",
+            "description": "**Hadrian Extension:** Owner ID for multi-tenancy",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "List of files",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/FileListResponse"
+                }
+              }
+            }
+          },
+          "400": {
+            "description": "Invalid request",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        },
+        "security": [
+          {
+            "api_key": []
+          }
+        ]
+      },
+      "post": {
+        "tags": [
+          "files"
+        ],
+        "summary": "Upload a file",
+        "description": "Uploads a file that can be used with vector stores for RAG.\nFiles are uploaded as multipart/form-data with the following fields:\n- `file`: The file to upload (required)\n- `purpose`: The intended purpose of the file (default: \"assistants\")\n- `owner_type`: Owner type - \"organization\", \"project\", or \"user\" (required)\n- `owner_id`: Owner ID (required)",
+        "operationId": "file_upload",
+        "requestBody": {
+          "description": "File upload with metadata",
+          "content": {
+            "multipart/form-data": {}
+          }
+        },
+        "responses": {
+          "200": {
+            "description": "File uploaded successfully",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/File"
+                }
+              }
+            }
+          },
+          "400": {
+            "description": "Invalid request",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "413": {
+            "description": "File too large",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "422": {
+            "description": "Virus detected in uploaded file",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        },
+        "security": [
+          {
+            "api_key": []
+          }
+        ]
+      }
+    },
+    "/api/v1/files/{file_id}": {
+      "get": {
+        "tags": [
+          "files"
+        ],
+        "summary": "Get file metadata",
+        "description": "Returns information about a specific file.",
+        "operationId": "file_get",
+        "parameters": [
+          {
+            "name": "file_id",
+            "in": "path",
+            "description": "File ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "File metadata",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/File"
+                }
+              }
+            }
+          },
+          "404": {
+            "description": "File not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        },
+        "security": [
+          {
+            "api_key": []
+          }
+        ]
+      },
+      "delete": {
+        "tags": [
+          "files"
+        ],
+        "summary": "Delete a file",
+        "description": "Deletes a file. The file cannot be deleted if it is still referenced by any vector stores.",
+        "operationId": "file_delete",
+        "parameters": [
+          {
+            "name": "file_id",
+            "in": "path",
+            "description": "File ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "File deleted",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/DeleteFileResponse"
+                }
+              }
+            }
+          },
+          "400": {
+            "description": "File is still in use",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "404": {
+            "description": "File not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        },
+        "security": [
+          {
+            "api_key": []
+          }
+        ]
+      }
+    },
+    "/api/v1/files/{file_id}/content": {
+      "get": {
+        "tags": [
+          "files"
+        ],
+        "summary": "Get file content",
+        "description": "Returns the content of a file.",
+        "operationId": "file_get_content",
+        "parameters": [
+          {
+            "name": "file_id",
+            "in": "path",
+            "description": "File ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "File content",
+            "content": {
+              "application/octet-stream": {}
+            }
+          },
+          "404": {
+            "description": "File not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        },
+        "security": [
+          {
+            "api_key": []
+          }
+        ]
+      }
+    },
+    "/api/v1/images/edits": {
+      "post": {
+        "tags": [
+          "Images"
+        ],
+        "summary": "Edit image with text instructions",
+        "description": "POST /v1/images/edits",
+        "operationId": "api_v1_images_edits",
+        "requestBody": {
+          "content": {
+            "multipart/form-data": {
+              "schema": {
+                "$ref": "#/components/schemas/CreateImageEditRequest"
+              }
+            }
+          },
+          "required": true
+        },
+        "responses": {
+          "200": {
+            "description": "Image edited successfully",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ImagesResponse"
+                }
+              }
+            }
+          },
+          "400": {
+            "description": "Bad request"
+          },
+          "500": {
+            "description": "Internal server error"
+          }
+        },
+        "security": [
+          {
+            "api_key": []
+          }
+        ]
+      }
+    },
+    "/api/v1/images/generations": {
+      "post": {
+        "tags": [
+          "Images"
+        ],
+        "summary": "Create image from text prompt",
+        "description": "POST /v1/images/generations",
+        "operationId": "api_v1_images_generations",
+        "requestBody": {
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/CreateImageRequest"
+              }
+            }
+          },
+          "required": true
+        },
+        "responses": {
+          "200": {
+            "description": "Image generated successfully",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ImagesResponse"
+                }
+              }
+            }
+          },
+          "400": {
+            "description": "Bad request"
+          },
+          "500": {
+            "description": "Internal server error"
+          }
+        },
+        "security": [
+          {
+            "api_key": []
+          }
+        ]
+      }
+    },
+    "/api/v1/images/variations": {
+      "post": {
+        "tags": [
+          "Images"
+        ],
+        "summary": "Create image variations",
+        "description": "POST /v1/images/variations",
+        "operationId": "api_v1_images_variations",
+        "requestBody": {
+          "content": {
+            "multipart/form-data": {
+              "schema": {
+                "$ref": "#/components/schemas/CreateImageVariationRequest"
+              }
+            }
+          },
+          "required": true
+        },
+        "responses": {
+          "200": {
+            "description": "Image variations created successfully",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ImagesResponse"
+                }
+              }
+            }
+          },
+          "400": {
+            "description": "Bad request"
+          },
+          "500": {
+            "description": "Internal server error"
+          }
+        },
+        "security": [
+          {
+            "api_key": []
+          }
+        ]
+      }
+    },
+    "/api/v1/models": {
+      "get": {
+        "tags": [
+          "models"
+        ],
+        "summary": "List available models",
+        "description": "Lists all models available from all configured providers.",
+        "operationId": "api_v1_models",
+        "responses": {
+          "200": {
+            "description": "List of available models",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/CombinedModelsResponse"
+                }
+              }
+            }
+          },
+          "400": {
+            "description": "Bad request",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        },
+        "security": [
+          {
+            "api_key": []
+          }
+        ]
+      }
+    },
+    "/api/v1/responses": {
+      "post": {
+        "tags": [
+          "chat"
+        ],
+        "summary": "Create a response",
+        "description": "Creates a model response using the Responses API format.",
+        "operationId": "api_v1_responses",
+        "requestBody": {
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/CreateResponsesPayload"
+              }
+            }
+          },
+          "required": true
+        },
+        "responses": {
+          "200": {
+            "description": "Response object (streaming or non-streaming)"
+          },
+          "400": {
+            "description": "Bad request",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "502": {
+            "description": "Provider error",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        },
+        "security": [
+          {
+            "api_key": []
+          }
+        ]
+      }
+    },
+    "/api/v1/tools/web-fetch": {
+      "post": {
+        "tags": [
+          "Tools"
+        ],
+        "summary": "Fetch a web page",
+        "description": "Fetches a URL and returns its content, optionally stripping HTML tags.\n\n**Hadrian Extension:** This endpoint is not part of the OpenAI API specification.",
+        "operationId": "web_fetch",
+        "requestBody": {
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/WebFetchRequest"
+              }
+            }
+          },
+          "required": true
+        },
+        "responses": {
+          "200": {
+            "description": "Fetched content",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/WebFetchResponse"
+                }
+              }
+            }
+          },
+          "400": {
+            "description": "Bad request or blocked URL"
+          },
+          "404": {
+            "description": "Web fetch not configured"
+          }
+        },
+        "security": [
+          {
+            "api_key": []
+          }
+        ]
+      }
+    },
+    "/api/v1/tools/web-search": {
+      "post": {
+        "tags": [
+          "Tools"
+        ],
+        "summary": "Search the web",
+        "description": "Performs a web search using the configured search provider (Tavily or Exa).\n\n**Hadrian Extension:** This endpoint is not part of the OpenAI API specification.",
+        "operationId": "web_search",
+        "requestBody": {
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/WebSearchRequest"
+              }
+            }
+          },
+          "required": true
+        },
+        "responses": {
+          "200": {
+            "description": "Search results",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/WebSearchResponse"
+                }
+              }
+            }
+          },
+          "400": {
+            "description": "Bad request"
+          },
+          "404": {
+            "description": "Web search not configured"
+          }
+        },
+        "security": [
+          {
+            "api_key": []
+          }
+        ]
+      }
+    },
+    "/api/v1/vector_stores": {
+      "get": {
+        "tags": [
+          "vector-stores"
+        ],
+        "summary": "List vector stores",
+        "description": "Returns a list of vector stores owned by the specified owner.",
+        "operationId": "vector_store_list",
+        "parameters": [
+          {
+            "name": "owner_type",
+            "in": "query",
+            "description": "**Hadrian Extension:** Owner type for multi-tenancy (organization, team, project, or user).\nWhen omitted along with `owner_id`, returns all accessible vector stores.",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          },
+          {
+            "name": "owner_id",
+            "in": "query",
+            "description": "**Hadrian Extension:** Owner ID for multi-tenancy.\nWhen omitted along with `owner_type`, returns all accessible vector stores.",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ],
+              "format": "uuid"
+            }
+          },
+          {
+            "name": "limit",
+            "in": "query",
+            "description": "Maximum number of vector stores to return (default: 20, max: 100)",
+            "required": false,
+            "schema": {
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "int64",
+              "maximum": 100,
+              "minimum": 1
+            }
+          },
+          {
+            "name": "order",
+            "in": "query",
+            "description": "Sort order by `created_at` timestamp (default: desc)",
+            "required": false,
+            "schema": {
+              "oneOf": [
+                {
+                  "type": "null"
+                },
+                {
+                  "$ref": "#/components/schemas/SortOrder"
+                }
+              ]
+            }
+          },
+          {
+            "name": "after",
+            "in": "query",
+            "description": "Cursor for forward pagination. Returns results after this object ID.\nUse the `last_id` from a previous response to get the next page.",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "example": "vs_550e8400-e29b-41d4-a716-446655440000"
+          },
+          {
+            "name": "before",
+            "in": "query",
+            "description": "Cursor for backward pagination. Returns results before this object ID.\nUse the `first_id` from a previous response to get the previous page.",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "example": "vs_550e8400-e29b-41d4-a716-446655440000"
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "List of vector stores",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/VectorStoreListResponse"
+                }
+              }
+            }
+          },
+          "400": {
+            "description": "Invalid request",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        },
+        "security": [
+          {
+            "api_key": []
+          }
+        ]
+      },
+      "post": {
+        "tags": [
+          "vector-stores"
+        ],
+        "summary": "Create a vector store",
+        "description": "Creates a new vector store for storing file embeddings.\nOptionally attaches files to the vector store at creation time via `file_ids`.",
+        "operationId": "vector_store_create",
+        "requestBody": {
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/CreateVectorStore"
+              }
+            }
+          },
+          "required": true
+        },
+        "responses": {
+          "201": {
+            "description": "Vector store created",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/VectorStore"
+                }
+              }
+            }
+          },
+          "400": {
+            "description": "Invalid request",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "404": {
+            "description": "Owner not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        },
+        "security": [
+          {
+            "api_key": []
+          }
+        ]
+      }
+    },
+    "/api/v1/vector_stores/{vector_store_id}": {
+      "get": {
+        "tags": [
+          "vector-stores"
+        ],
+        "summary": "Get a vector store",
+        "description": "Retrieves a vector store by ID.",
+        "operationId": "vector_store_get",
+        "parameters": [
+          {
+            "name": "vector_store_id",
+            "in": "path",
+            "description": "Vector store ID (e.g., vs_550e8400-e29b-41d4-a716-446655440000)",
+            "required": true,
+            "schema": {
+              "type": "string"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Vector store details",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/VectorStore"
+                }
+              }
+            }
+          },
+          "404": {
+            "description": "Vector store not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        },
+        "security": [
+          {
+            "api_key": []
+          }
+        ]
+      },
+      "post": {
+        "tags": [
+          "vector-stores"
+        ],
+        "summary": "Modify a vector store",
+        "description": "Modifies a vector store's metadata.",
+        "operationId": "vector_store_modify",
+        "parameters": [
+          {
+            "name": "vector_store_id",
+            "in": "path",
+            "description": "Vector store ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          }
+        ],
+        "requestBody": {
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/UpdateVectorStore"
+              }
+            }
+          },
+          "required": true
+        },
+        "responses": {
+          "200": {
+            "description": "Vector store updated",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/VectorStore"
+                }
+              }
+            }
+          },
+          "404": {
+            "description": "Vector store not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        },
+        "security": [
+          {
+            "api_key": []
+          }
+        ]
+      },
+      "delete": {
+        "tags": [
+          "vector-stores"
+        ],
+        "summary": "Delete a vector store",
+        "description": "Deletes a vector store and all its files (soft delete).",
+        "operationId": "vector_store_delete",
+        "parameters": [
+          {
+            "name": "vector_store_id",
+            "in": "path",
+            "description": "Vector store ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Vector store deleted",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/DeleteVectorStoreResponse"
+                }
+              }
+            }
+          },
+          "404": {
+            "description": "Vector store not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        },
+        "security": [
+          {
+            "api_key": []
+          }
+        ]
+      }
+    },
+    "/api/v1/vector_stores/{vector_store_id}/file_batches": {
+      "post": {
+        "tags": [
+          "vector-stores"
+        ],
+        "summary": "Create a file batch",
+        "description": "Creates a batch of files to be added to a vector store.\nNote: File batches are not yet fully implemented. This endpoint creates\nfiles individually and returns a batch representation.\n\n## Content Deduplication\n\nFiles are deduplicated by content hash (SHA-256). If a file with identical content\nalready exists in the vector store, it is counted as \"completed\" in the batch\nresponse but no re-processing occurs. This prevents duplicate chunks and wasted\ncompute while still reporting success for the file.\n\nThe `file_counts.completed` field in the response includes both newly processed\nfiles and deduplicated files.\n\n## Embedding Model Validation\n\nThe gateway validates that its configured embedding model matches the vector store's\nembedding model before processing any files in the batch. This prevents incompatible\nembeddings from being stored together. If there's a mismatch, a 409 Conflict error\nis returned with details about the expected vs. configured models.",
+        "operationId": "vector_store_file_batch_create",
+        "parameters": [
+          {
+            "name": "vector_store_id",
+            "in": "path",
+            "description": "Vector store ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          }
+        ],
+        "requestBody": {
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/CreateFileBatchRequest"
+              }
+            }
+          },
+          "required": true
+        },
+        "responses": {
+          "201": {
+            "description": "File batch created",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/FileBatch"
+                }
+              }
+            }
+          },
+          "400": {
+            "description": "Invalid request",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "404": {
+            "description": "Vector store not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "409": {
+            "description": "Embedding model mismatch",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "503": {
+            "description": "File search service not configured",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        },
+        "security": [
+          {
+            "api_key": []
+          }
+        ]
+      }
+    },
+    "/api/v1/vector_stores/{vector_store_id}/file_batches/{batch_id}": {
+      "get": {
+        "tags": [
+          "vector-stores"
+        ],
+        "summary": "Get a file batch",
+        "description": "Retrieves a file batch. Note: File batches are executed synchronously,\nso this endpoint returns a \"completed\" or \"failed\" status.",
+        "operationId": "vector_store_file_batch_get",
+        "parameters": [
+          {
+            "name": "vector_store_id",
+            "in": "path",
+            "description": "Vector store ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          },
+          {
+            "name": "batch_id",
+            "in": "path",
+            "description": "File batch ID",
+            "required": true,
+            "schema": {
+              "type": "string"
+            }
+          }
+        ],
+        "responses": {
+          "404": {
+            "description": "File batches are not persisted",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        },
+        "security": [
+          {
+            "api_key": []
+          }
+        ]
+      },
+      "delete": {
+        "tags": [
+          "vector-stores"
+        ],
+        "summary": "Cancel a file batch",
+        "description": "Cancels a file batch. Note: File batches are executed synchronously,\nso cancellation is not supported.",
+        "operationId": "vector_store_file_batch_cancel",
+        "parameters": [
+          {
+            "name": "vector_store_id",
+            "in": "path",
+            "description": "Vector store ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          },
+          {
+            "name": "batch_id",
+            "in": "path",
+            "description": "File batch ID",
+            "required": true,
+            "schema": {
+              "type": "string"
+            }
+          }
+        ],
+        "responses": {
+          "400": {
+            "description": "File batches cannot be cancelled",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        },
+        "security": [
+          {
+            "api_key": []
+          }
+        ]
+      }
+    },
+    "/api/v1/vector_stores/{vector_store_id}/file_batches/{batch_id}/files": {
+      "get": {
+        "tags": [
+          "vector-stores"
+        ],
+        "summary": "List files in a batch",
+        "description": "Lists files in a file batch. Note: File batches are not persisted.",
+        "operationId": "vector_store_file_batch_list_files",
+        "parameters": [
+          {
+            "name": "vector_store_id",
+            "in": "path",
+            "description": "Vector store ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          },
+          {
+            "name": "batch_id",
+            "in": "path",
+            "description": "File batch ID",
+            "required": true,
+            "schema": {
+              "type": "string"
+            }
+          }
+        ],
+        "responses": {
+          "404": {
+            "description": "File batches are not persisted",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        },
+        "security": [
+          {
+            "api_key": []
+          }
+        ]
+      }
+    },
+    "/api/v1/vector_stores/{vector_store_id}/files": {
+      "get": {
+        "tags": [
+          "vector-stores"
+        ],
+        "summary": "List vector store files",
+        "description": "Returns a list of files in a vector store.",
+        "operationId": "vector_store_file_list",
+        "parameters": [
+          {
+            "name": "vector_store_id",
+            "in": "path",
+            "description": "Vector store ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          },
+          {
+            "name": "limit",
+            "in": "query",
+            "description": "Maximum number of files to return (default: 20, max: 100)",
+            "required": false,
+            "schema": {
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "int64",
+              "maximum": 100,
+              "minimum": 1
+            }
+          },
+          {
+            "name": "order",
+            "in": "query",
+            "description": "Sort order by `created_at` timestamp (default: desc)",
+            "required": false,
+            "schema": {
+              "oneOf": [
+                {
+                  "type": "null"
+                },
+                {
+                  "$ref": "#/components/schemas/SortOrder"
+                }
+              ]
+            }
+          },
+          {
+            "name": "after",
+            "in": "query",
+            "description": "Cursor for forward pagination. Returns results after this file ID.",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "example": "vsf_550e8400-e29b-41d4-a716-446655440000"
+          },
+          {
+            "name": "before",
+            "in": "query",
+            "description": "Cursor for backward pagination. Returns results before this file ID.",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "example": "vsf_550e8400-e29b-41d4-a716-446655440000"
+          },
+          {
+            "name": "filter",
+            "in": "query",
+            "description": "Filter by status (in_progress, completed, failed, cancelled)",
+            "required": false,
+            "schema": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "List of files",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/VectorStoreFileListResponse"
+                }
+              }
+            }
+          },
+          "404": {
+            "description": "Vector store not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        },
+        "security": [
+          {
+            "api_key": []
+          }
+        ]
+      },
+      "post": {
+        "tags": [
+          "vector-stores"
+        ],
+        "summary": "Create a vector store file",
+        "description": "Adds a file to a vector store. The file must already exist in the Files API.\nProcessing will start automatically after the file is added.\n\n## Content Deduplication\n\nFiles are deduplicated by content hash (SHA-256). If a file with identical content\nalready exists in the vector store, the existing file is returned with status 200\ninstead of creating a duplicate. This is idempotent behavior—uploading the same\ncontent multiple times has no additional effect.\n\n## Embedding Model Validation\n\nThe gateway validates that its configured embedding model matches the vector store's\nembedding model before adding files. This prevents incompatible embeddings from being\nstored together. If there's a mismatch, a 409 Conflict error is returned with details\nabout the expected vs. configured models.\n\n- **201 Created**: New file added, processing started\n- **200 OK**: Duplicate content detected, existing file returned (no re-processing)\n- **409 Conflict**: Embedding model mismatch between gateway configuration and vector store",
+        "operationId": "vector_store_file_create",
+        "parameters": [
+          {
+            "name": "vector_store_id",
+            "in": "path",
+            "description": "Vector store ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          }
+        ],
+        "requestBody": {
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/CreateVectorStoreFileRequest"
+              }
+            }
+          },
+          "required": true
+        },
+        "responses": {
+          "200": {
+            "description": "Duplicate content detected, existing file returned",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/VectorStoreFile"
+                }
+              }
+            }
+          },
+          "201": {
+            "description": "File added to vector store",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/VectorStoreFile"
+                }
+              }
+            }
+          },
+          "400": {
+            "description": "Invalid request",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "404": {
+            "description": "Vector store or file not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "409": {
+            "description": "Embedding model mismatch",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "503": {
+            "description": "File search service not configured",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        },
+        "security": [
+          {
+            "api_key": []
+          }
+        ]
+      }
+    },
+    "/api/v1/vector_stores/{vector_store_id}/files/{file_id}": {
+      "get": {
+        "tags": [
+          "vector-stores"
+        ],
+        "summary": "Get a vector store file",
+        "description": "Retrieves a file from a vector store.",
+        "operationId": "vector_store_file_get",
+        "parameters": [
+          {
+            "name": "vector_store_id",
+            "in": "path",
+            "description": "Vector store ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          },
+          {
+            "name": "file_id",
+            "in": "path",
+            "description": "Vector store file ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Vector store file details",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/VectorStoreFile"
+                }
+              }
+            }
+          },
+          "404": {
+            "description": "Vector store or file not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        },
+        "security": [
+          {
+            "api_key": []
+          }
+        ]
+      },
+      "delete": {
+        "tags": [
+          "vector-stores"
+        ],
+        "summary": "Delete a vector store file",
+        "description": "Removes a file from a vector store. This does not delete the underlying file\nfrom the Files API.",
+        "operationId": "vector_store_file_delete",
+        "parameters": [
+          {
+            "name": "vector_store_id",
+            "in": "path",
+            "description": "Vector store ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          },
+          {
+            "name": "file_id",
+            "in": "path",
+            "description": "Vector store file ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "File removed from vector store",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/DeleteVectorStoreFileResponse"
+                }
+              }
+            }
+          },
+          "404": {
+            "description": "Vector store or file not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        },
+        "security": [
+          {
+            "api_key": []
+          }
+        ]
+      }
+    },
+    "/api/v1/vector_stores/{vector_store_id}/files/{file_id}/chunks": {
+      "get": {
+        "tags": [
+          "vector-stores"
+        ],
+        "summary": "List chunks for a file [Hadrian Extension]",
+        "description": "**Hadrian Extension** - This endpoint is not part of the standard OpenAI API.\n\nReturns all chunks that have been extracted and embedded from a file. Useful for debugging chunking behavior and verifying embeddings.",
+        "operationId": "vector_store_file_chunks_list",
+        "parameters": [
+          {
+            "name": "vector_store_id",
+            "in": "path",
+            "description": "Vector store ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          },
+          {
+            "name": "file_id",
+            "in": "path",
+            "description": "Vector store file ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "List of chunks for the file",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ChunkListResponse"
+                }
+              }
+            }
+          },
+          "404": {
+            "description": "Vector store or file not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "503": {
+            "description": "File search not configured",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        },
+        "security": [
+          {
+            "api_key": []
+          }
+        ]
+      }
+    },
+    "/api/v1/vector_stores/{vector_store_id}/search": {
+      "post": {
+        "tags": [
+          "vector-stores"
+        ],
+        "summary": "Search vector store",
+        "description": "Performs a semantic search against a vector store.\n\n**Hadrian Extensions:** The response schema includes additional fields not in the standard OpenAI API:\n- `chunk_id`, `vector_store_id`, `chunk_index` (debugging info)",
+        "operationId": "vector_store_search",
+        "parameters": [
+          {
+            "name": "vector_store_id",
+            "in": "path",
+            "description": "Vector store ID",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "uuid"
+            }
+          }
+        ],
+        "requestBody": {
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/VectorStoreSearchRequest"
+              }
+            }
+          },
+          "required": true
+        },
+        "responses": {
+          "200": {
+            "description": "Search results",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/VectorStoreSearchResponse"
+                }
+              }
+            }
+          },
+          "400": {
+            "description": "Invalid request",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "404": {
+            "description": "Vector store not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          },
+          "503": {
+            "description": "File search not configured",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ErrorResponse"
+                }
+              }
+            }
+          }
+        },
+        "security": [
+          {
+            "api_key": []
+          }
+        ]
+      }
+    },
+    "/health": {
+      "get": {
+        "tags": [
+          "health"
+        ],
+        "summary": "Full health check with subsystem status.",
+        "description": "Returns detailed status of all subsystems including database, cache, and secrets manager.\nUse this endpoint for comprehensive health monitoring and dashboards.",
+        "operationId": "health_check",
+        "responses": {
+          "200": {
+            "description": "Service is healthy",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/HealthStatus"
+                }
+              }
+            }
+          },
+          "503": {
+            "description": "Service is unhealthy",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/HealthStatus"
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/health/live": {
+      "get": {
+        "tags": [
+          "health"
+        ],
+        "summary": "Kubernetes liveness probe.",
+        "description": "Returns 200 if the service is running. This endpoint should always succeed\nunless the service process is completely broken. Use this for Kubernetes\nliveness probes to detect and restart unhealthy pods.",
+        "operationId": "health_liveness",
+        "responses": {
+          "200": {
+            "description": "Service is alive"
+          }
+        }
+      }
+    },
+    "/health/ready": {
+      "get": {
+        "tags": [
+          "health"
+        ],
+        "summary": "Kubernetes readiness probe.",
+        "description": "Returns 200 if the service is ready to accept traffic. Checks that critical\ndependencies (database) are available. Use this for Kubernetes readiness\nprobes to control traffic routing to pods.",
+        "operationId": "health_readiness",
+        "responses": {
+          "200": {
+            "description": "Service is ready to accept traffic"
+          },
+          "503": {
             "description": "Service is not ready (database unavailable)"
           }
         }
@@ -13320,6 +18779,17 @@
               "type": "string"
             },
             "description": "Permission scopes (null = full access)\nValid scopes: chat, completions, embeddings, images, audio, files, models, admin"
+          },
+          "sovereignty_requirements": {
+            "oneOf": [
+              {
+                "type": "null"
+              },
+              {
+                "$ref": "#/components/schemas/SovereigntyRequirements",
+                "description": "Sovereignty requirements that restrict which models this key can access"
+              }
+            ]
           }
         }
       },
@@ -13756,6 +19226,46 @@
           "monthly"
         ]
       },
+      "BuiltInProvider": {
+        "type": "object",
+        "description": "Built-in provider summary",
+        "required": [
+          "name",
+          "provider_type"
+        ],
+        "properties": {
+          "base_url": {
+            "type": [
+              "string",
+              "null"
+            ],
+            "description": "Base URL (if applicable)"
+          },
+          "name": {
+            "type": "string",
+            "description": "Provider name (as configured in hadrian.toml)"
+          },
+          "provider_type": {
+            "type": "string",
+            "description": "Provider type (e.g., \"open_ai\", \"anthropic\")"
+          }
+        }
+      },
+      "BuiltInProvidersResponse": {
+        "type": "object",
+        "description": "List of built-in providers from the gateway configuration",
+        "required": [
+          "data"
+        ],
+        "properties": {
+          "data": {
+            "type": "array",
+            "items": {
+              "$ref": "#/components/schemas/BuiltInProvider"
+            }
+          }
+        }
+      },
       "BulkUpsertResponse": {
         "type": "object",
         "description": "Response for bulk upsert operation",
@@ -14077,6 +19587,33 @@
           }
         }
       },
+      "ConnectivityTestResponse": {
+        "type": "object",
+        "description": "Result of a provider connectivity test",
+        "required": [
+          "status",
+          "message"
+        ],
+        "properties": {
+          "latency_ms": {
+            "type": [
+              "integer",
+              "null"
+            ],
+            "format": "int64",
+            "description": "Latency in milliseconds",
+            "minimum": 0
+          },
+          "message": {
+            "type": "string",
+            "description": "Human-readable message"
+          },
+          "status": {
+            "type": "string",
+            "description": "Whether the test was successful"
+          }
+        }
+      },
       "ContentPart": {
         "oneOf": [
           {
@@ -14601,6 +20138,17 @@
               "type": "string"
             },
             "description": "Permission scopes (null = full access)"
+          },
+          "sovereignty_requirements": {
+            "oneOf": [
+              {
+                "type": "null"
+              },
+              {
+                "$ref": "#/components/schemas/SovereigntyRequirements",
+                "description": "Sovereignty requirements for model access"
+              }
+            ]
           }
         }
       },
@@ -14714,6 +20262,17 @@
             "format": "int64",
             "description": "Random seed for reproducibility"
           },
+          "sovereignty_requirements": {
+            "oneOf": [
+              {
+                "type": "null"
+              },
+              {
+                "$ref": "#/components/schemas/SovereigntyRequirements",
+                "description": "**Hadrian Extension:** Per-request sovereignty requirements.\nMerged with API key requirements (most restrictive wins)."
+              }
+            ]
+          },
           "stop": {
             "oneOf": [
               {
@@ -14924,6 +20483,17 @@
             "format": "int64",
             "description": "Random seed for reproducibility"
           },
+          "sovereignty_requirements": {
+            "oneOf": [
+              {
+                "type": "null"
+              },
+              {
+                "$ref": "#/components/schemas/SovereigntyRequirements",
+                "description": "**Hadrian Extension:** Per-request sovereignty requirements.\nMerged with API key requirements (most restrictive wins)."
+              }
+            ]
+          },
           "stop": {
             "type": "object",
             "description": "Stop sequence(s)"
@@ -15018,19 +20588,22 @@
         "required": [
           "name",
           "owner",
-          "provider_type",
-          "base_url"
+          "provider_type"
         ],
         "properties": {
-          "api_key_secret_ref": {
+          "api_key": {
             "type": [
               "string",
               "null"
             ],
-            "description": "Reference to API key in secrets manager"
+            "description": "Raw API key (stored in secrets manager if available, otherwise stored directly)"
           },
           "base_url": {
-            "type": "string"
+            "type": "string",
+            "description": "Base URL for the provider (required for OpenAI/Anthropic/Azure, optional for Bedrock/Vertex)"
+          },
+          "config": {
+            "description": "Provider-specific configuration (e.g., region, credentials for Bedrock/Vertex)"
           },
           "models": {
             "type": [
@@ -15050,7 +20623,18 @@
           },
           "provider_type": {
             "type": "string",
-            "description": "Provider type (e.g., \"open_ai\", \"anthropic\")"
+            "description": "Provider type (e.g., \"open_ai\", \"anthropic\", \"bedrock\", \"vertex\")"
+          },
+          "sovereignty": {
+            "oneOf": [
+              {
+                "type": "null"
+              },
+              {
+                "$ref": "#/components/schemas/SovereigntyMetadata",
+                "description": "Sovereignty and compliance metadata"
+              }
+            ]
           }
         }
       },
@@ -15070,76 +20654,203 @@
             "format": "int64",
             "description": "Number of dimensions for output embeddings"
           },
-          "encoding_format": {
+          "encoding_format": {
+            "oneOf": [
+              {
+                "type": "null"
+              },
+              {
+                "$ref": "#/components/schemas/EncodingFormat",
+                "description": "Output encoding format"
+              }
+            ]
+          },
+          "input": {
+            "$ref": "#/components/schemas/EmbeddingInput",
+            "description": "Input to embed"
+          },
+          "input_type": {
+            "type": [
+              "string",
+              "null"
+            ],
+            "description": "**Hadrian Extension:** Input type hint for embedding providers that support it (e.g., Cohere)"
+          },
+          "model": {
+            "type": "string",
+            "description": "Model to use for embedding"
+          },
+          "provider": {
+            "type": "object",
+            "description": "**Hadrian Extension:** Provider routing configuration"
+          },
+          "sovereignty_requirements": {
+            "oneOf": [
+              {
+                "type": "null"
+              },
+              {
+                "$ref": "#/components/schemas/SovereigntyRequirements",
+                "description": "**Hadrian Extension:** Per-request sovereignty requirements.\nMerged with API key requirements (most restrictive wins)."
+              }
+            ]
+          },
+          "user": {
+            "type": [
+              "string",
+              "null"
+            ],
+            "description": "User identifier for abuse detection"
+          }
+        }
+      },
+      "CreateFileBatchRequest": {
+        "type": "object",
+        "description": "Create file batch request",
+        "required": [
+          "file_ids"
+        ],
+        "properties": {
+          "chunking_strategy": {
+            "oneOf": [
+              {
+                "type": "null"
+              },
+              {
+                "$ref": "#/components/schemas/ChunkingStrategy",
+                "description": "Chunking strategy for all files in the batch"
+              }
+            ]
+          },
+          "file_ids": {
+            "type": "array",
+            "items": {
+              "type": "string",
+              "format": "uuid"
+            },
+            "description": "File IDs to add to the batch"
+          }
+        }
+      },
+      "CreateImageEditRequest": {
+        "type": "object",
+        "description": "Create image edit request (POST /v1/images/edits)\n\nNote: This endpoint accepts multipart/form-data. The `image` and `mask`\nfields are file uploads, not JSON fields.",
+        "required": [
+          "prompt"
+        ],
+        "properties": {
+          "background": {
+            "oneOf": [
+              {
+                "type": "null"
+              },
+              {
+                "$ref": "#/components/schemas/ImageBackground",
+                "description": "Background transparency setting. GPT image models only."
+              }
+            ]
+          },
+          "model": {
+            "type": [
+              "string",
+              "null"
+            ],
+            "description": "The model to use for image editing."
+          },
+          "n": {
+            "type": [
+              "integer",
+              "null"
+            ],
+            "format": "int32",
+            "description": "Number of images to generate (1-10)."
+          },
+          "output_compression": {
+            "type": [
+              "integer",
+              "null"
+            ],
+            "format": "int32",
+            "description": "Compression level (0-100%) for webp/jpeg output."
+          },
+          "output_format": {
             "oneOf": [
               {
                 "type": "null"
               },
               {
-                "$ref": "#/components/schemas/EncodingFormat",
-                "description": "Output encoding format"
+                "$ref": "#/components/schemas/ImageOutputFormat",
+                "description": "Output format for GPT image models (png, jpeg, webp)."
               }
             ]
           },
-          "input": {
-            "$ref": "#/components/schemas/EmbeddingInput",
-            "description": "Input to embed"
-          },
-          "input_type": {
-            "type": [
-              "string",
-              "null"
-            ],
-            "description": "**Hadrian Extension:** Input type hint for embedding providers that support it (e.g., Cohere)"
+          "partial_images": {
+            "oneOf": [
+              {
+                "type": "null"
+              },
+              {
+                "$ref": "#/components/schemas/PartialImages",
+                "description": "Partial images configuration for streaming."
+              }
+            ]
           },
-          "model": {
+          "prompt": {
             "type": "string",
-            "description": "Model to use for embedding"
+            "description": "A text description of the desired edit.\nMax 1000 chars for dall-e-2, 32000 for GPT image models."
           },
-          "provider": {
-            "type": "object",
-            "description": "**Hadrian Extension:** Provider routing configuration"
+          "quality": {
+            "oneOf": [
+              {
+                "type": "null"
+              },
+              {
+                "$ref": "#/components/schemas/ImageQuality",
+                "description": "The quality of the generated image."
+              }
+            ]
           },
-          "user": {
-            "type": [
-              "string",
-              "null"
-            ],
-            "description": "User identifier for abuse detection"
-          }
-        }
-      },
-      "CreateFileBatchRequest": {
-        "type": "object",
-        "description": "Create file batch request",
-        "required": [
-          "file_ids"
-        ],
-        "properties": {
-          "chunking_strategy": {
+          "response_format": {
             "oneOf": [
               {
                 "type": "null"
               },
               {
-                "$ref": "#/components/schemas/ChunkingStrategy",
-                "description": "Chunking strategy for all files in the batch"
+                "$ref": "#/components/schemas/ImageResponseFormat",
+                "description": "Format for returning generated images (url or b64_json)."
               }
             ]
           },
-          "file_ids": {
-            "type": "array",
-            "items": {
-              "type": "string",
-              "format": "uuid"
-            },
-            "description": "File IDs to add to the batch"
+          "size": {
+            "oneOf": [
+              {
+                "type": "null"
+              },
+              {
+                "$ref": "#/components/schemas/ImageSize",
+                "description": "Size of the generated images."
+              }
+            ]
+          },
+          "stream": {
+            "type": [
+              "boolean",
+              "null"
+            ],
+            "description": "Edit image in streaming mode. GPT image models only."
+          },
+          "user": {
+            "type": [
+              "string",
+              "null"
+            ],
+            "description": "Unique identifier for the end-user for abuse detection."
           }
         }
       },
-      "CreateImageEditRequest": {
+      "CreateImageRequest": {
         "type": "object",
-        "description": "Create image edit request (POST /v1/images/edits)\n\nNote: This endpoint accepts multipart/form-data. The `image` and `mask`\nfields are file uploads, not JSON fields.",
+        "description": "Create image generation request (POST /v1/images/generations)",
         "required": [
           "prompt"
         ],
@@ -15160,7 +20871,18 @@
               "string",
               "null"
             ],
-            "description": "The model to use for image editing."
+            "description": "The model to use for image generation."
+          },
+          "moderation": {
+            "oneOf": [
+              {
+                "type": "null"
+              },
+              {
+                "$ref": "#/components/schemas/ImageModeration",
+                "description": "Content moderation level. GPT image models only."
+              }
+            ]
           },
           "n": {
             "type": [
@@ -15168,7 +20890,7 @@
               "null"
             ],
             "format": "int32",
-            "description": "Number of images to generate (1-10)."
+            "description": "Number of images to generate (1-10). For dall-e-3, only n=1 is supported."
           },
           "output_compression": {
             "type": [
@@ -15176,7 +20898,7 @@
               "null"
             ],
             "format": "int32",
-            "description": "Compression level (0-100%) for webp/jpeg output."
+            "description": "Compression level (0-100%) for webp/jpeg output. GPT image models only."
           },
           "output_format": {
             "oneOf": [
@@ -15202,7 +20924,7 @@
           },
           "prompt": {
             "type": "string",
-            "description": "A text description of the desired edit.\nMax 1000 chars for dall-e-2, 32000 for GPT image models."
+            "description": "A text description of the desired image(s).\nMax 32000 chars for GPT image models, 1000 for dall-e-2, 4000 for dall-e-3."
           },
           "quality": {
             "oneOf": [
@@ -15237,648 +20959,1017 @@
               }
             ]
           },
-          "stream": {
+          "sovereignty_requirements": {
+            "oneOf": [
+              {
+                "type": "null"
+              },
+              {
+                "$ref": "#/components/schemas/SovereigntyRequirements",
+                "description": "**Hadrian Extension:** Per-request sovereignty requirements.\nMerged with API key requirements (most restrictive wins)."
+              }
+            ]
+          },
+          "stream": {
+            "type": [
+              "boolean",
+              "null"
+            ],
+            "description": "Generate image in streaming mode. GPT image models only."
+          },
+          "style": {
+            "oneOf": [
+              {
+                "type": "null"
+              },
+              {
+                "$ref": "#/components/schemas/ImageStyle",
+                "description": "Image style. dall-e-3 only."
+              }
+            ]
+          },
+          "user": {
+            "type": [
+              "string",
+              "null"
+            ],
+            "description": "Unique identifier for the end-user for abuse detection."
+          }
+        }
+      },
+      "CreateImageVariationRequest": {
+        "type": "object",
+        "description": "Create image variation request (POST /v1/images/variations)\n\nNote: This endpoint accepts multipart/form-data. The `image` field\nis a file upload, not a JSON field.",
+        "properties": {
+          "model": {
+            "type": [
+              "string",
+              "null"
+            ],
+            "description": "The model to use. Only dall-e-2 is supported for variations."
+          },
+          "n": {
+            "type": [
+              "integer",
+              "null"
+            ],
+            "format": "int32",
+            "description": "Number of images to generate (1-10)."
+          },
+          "response_format": {
+            "oneOf": [
+              {
+                "type": "null"
+              },
+              {
+                "$ref": "#/components/schemas/ImageResponseFormat",
+                "description": "Format for returning generated images (url or b64_json)."
+              }
+            ]
+          },
+          "size": {
+            "oneOf": [
+              {
+                "type": "null"
+              },
+              {
+                "$ref": "#/components/schemas/ImageSize",
+                "description": "Size of the generated images."
+              }
+            ]
+          },
+          "user": {
+            "type": [
+              "string",
+              "null"
+            ],
+            "description": "Unique identifier for the end-user for abuse detection."
+          }
+        }
+      },
+      "CreateModelPricing": {
+        "type": "object",
+        "description": "Request to create model pricing",
+        "required": [
+          "owner",
+          "provider",
+          "model"
+        ],
+        "properties": {
+          "cache_write_per_1m_tokens": {
+            "type": [
+              "integer",
+              "null"
+            ],
+            "format": "int64",
+            "description": "Cost per 1M cache write tokens in microcents"
+          },
+          "cached_input_per_1m_tokens": {
+            "type": [
+              "integer",
+              "null"
+            ],
+            "format": "int64",
+            "description": "Cost per 1M cached input tokens in microcents"
+          },
+          "input_per_1m_tokens": {
+            "type": "integer",
+            "format": "int64",
+            "description": "Cost per 1M input tokens in microcents"
+          },
+          "model": {
+            "type": "string"
+          },
+          "output_per_1m_tokens": {
+            "type": "integer",
+            "format": "int64",
+            "description": "Cost per 1M output tokens in microcents"
+          },
+          "owner": {
+            "$ref": "#/components/schemas/PricingOwner"
+          },
+          "per_1m_characters": {
+            "type": [
+              "integer",
+              "null"
+            ],
+            "format": "int64",
+            "description": "Cost per 1M characters in microcents (for TTS)"
+          },
+          "per_image": {
+            "type": [
+              "integer",
+              "null"
+            ],
+            "format": "int64",
+            "description": "Cost per image in microcents"
+          },
+          "per_request": {
             "type": [
-              "boolean",
+              "integer",
               "null"
             ],
-            "description": "Edit image in streaming mode. GPT image models only."
+            "format": "int64",
+            "description": "Cost per request in microcents"
           },
-          "user": {
+          "per_second": {
             "type": [
-              "string",
+              "integer",
               "null"
             ],
-            "description": "Unique identifier for the end-user for abuse detection."
+            "format": "int64",
+            "description": "Cost per second of audio in microcents (for transcription/translation)"
+          },
+          "provider": {
+            "type": "string"
+          },
+          "reasoning_per_1m_tokens": {
+            "type": [
+              "integer",
+              "null"
+            ],
+            "format": "int64",
+            "description": "Cost per 1M reasoning tokens in microcents"
+          },
+          "source": {
+            "$ref": "#/components/schemas/PricingSource"
           }
         }
       },
-      "CreateImageRequest": {
+      "CreateOrgRbacPolicy": {
         "type": "object",
-        "description": "Create image generation request (POST /v1/images/generations)",
+        "description": "Request to create a new organization RBAC policy.",
         "required": [
-          "prompt"
+          "name",
+          "condition"
         ],
         "properties": {
-          "background": {
-            "oneOf": [
-              {
-                "type": "null"
-              },
-              {
-                "$ref": "#/components/schemas/ImageBackground",
-                "description": "Background transparency setting. GPT image models only."
-              }
-            ]
+          "action": {
+            "type": "string",
+            "description": "Action pattern to match (e.g., \"read\", \"write\", \"delete\", \"*\")"
           },
-          "model": {
+          "condition": {
+            "type": "string",
+            "description": "CEL expression that must evaluate to true for the policy to apply"
+          },
+          "description": {
             "type": [
               "string",
               "null"
             ],
-            "description": "The model to use for image generation."
+            "description": "Optional description of what this policy does"
           },
-          "moderation": {
-            "oneOf": [
-              {
-                "type": "null"
-              },
-              {
-                "$ref": "#/components/schemas/ImageModeration",
-                "description": "Content moderation level. GPT image models only."
-              }
-            ]
+          "effect": {
+            "$ref": "#/components/schemas/RbacPolicyEffect",
+            "description": "Policy effect when condition matches (defaults to 'deny')"
           },
-          "n": {
+          "enabled": {
+            "type": "boolean",
+            "description": "Whether this policy is active (defaults to true)"
+          },
+          "name": {
+            "type": "string",
+            "description": "Human-readable name for this policy (unique per org)"
+          },
+          "priority": {
+            "type": "integer",
+            "format": "int32",
+            "description": "Priority for evaluation order (higher = evaluated first, defaults to 0)\nValid range: -1000 to 1000"
+          },
+          "reason": {
             "type": [
-              "integer",
+              "string",
               "null"
             ],
-            "format": "int32",
-            "description": "Number of images to generate (1-10). For dall-e-3, only n=1 is supported."
+            "description": "Reason for creating this policy (stored in version history)"
           },
-          "output_compression": {
+          "resource": {
+            "type": "string",
+            "description": "Resource pattern to match (e.g., \"projects/*\", \"teams/engineering/*\", \"*\")"
+          }
+        }
+      },
+      "CreateOrgScimConfig": {
+        "type": "object",
+        "description": "Request to create a new organization SCIM configuration.",
+        "properties": {
+          "create_users": {
+            "type": "boolean",
+            "description": "Whether to create new users when they don't exist (default: true)"
+          },
+          "deactivate_deletes_user": {
+            "type": "boolean",
+            "description": "Whether deactivating a user deletes them entirely (default: false)"
+          },
+          "default_org_role": {
+            "type": "string",
+            "description": "Default role for new users in the organization (default: \"member\")"
+          },
+          "default_team_id": {
             "type": [
-              "integer",
+              "string",
               "null"
             ],
-            "format": "int32",
-            "description": "Compression level (0-100%) for webp/jpeg output. GPT image models only."
+            "format": "uuid",
+            "description": "Default team to add new users to (optional)"
           },
-          "output_format": {
-            "oneOf": [
-              {
-                "type": "null"
-              },
-              {
-                "$ref": "#/components/schemas/ImageOutputFormat",
-                "description": "Output format for GPT image models (png, jpeg, webp)."
-              }
-            ]
+          "default_team_role": {
+            "type": "string",
+            "description": "Default role for new users in the default team (default: \"member\")"
           },
-          "partial_images": {
-            "oneOf": [
-              {
-                "type": "null"
-              },
-              {
-                "$ref": "#/components/schemas/PartialImages",
-                "description": "Partial images configuration for streaming."
-              }
-            ]
+          "enabled": {
+            "type": "boolean",
+            "description": "Whether SCIM provisioning is enabled (default: true)"
           },
-          "prompt": {
-            "type": "string",
-            "description": "A text description of the desired image(s).\nMax 32000 chars for GPT image models, 1000 for dall-e-2, 4000 for dall-e-3."
+          "revoke_api_keys_on_deactivate": {
+            "type": "boolean",
+            "description": "Whether to revoke all API keys when user is deactivated (default: true)"
           },
-          "quality": {
-            "oneOf": [
-              {
-                "type": "null"
-              },
-              {
-                "$ref": "#/components/schemas/ImageQuality",
-                "description": "The quality of the generated image."
-              }
-            ]
+          "sync_display_name": {
+            "type": "boolean",
+            "description": "Whether to sync display name from SCIM on updates (default: true)"
+          }
+        }
+      },
+      "CreateOrgSsoConfig": {
+        "type": "object",
+        "description": "Request to create a new organization SSO configuration.",
+        "properties": {
+          "allowed_email_domains": {
+            "type": "array",
+            "items": {
+              "type": "string"
+            },
+            "description": "Allowed email domains (empty = allow all)"
           },
-          "response_format": {
-            "oneOf": [
-              {
-                "type": "null"
-              },
-              {
-                "$ref": "#/components/schemas/ImageResponseFormat",
-                "description": "Format for returning generated images (url or b64_json)."
-              }
-            ]
+          "client_id": {
+            "type": [
+              "string",
+              "null"
+            ],
+            "description": "OAuth2 client ID (required for OIDC, not used for SAML)"
           },
-          "size": {
-            "oneOf": [
-              {
-                "type": "null"
-              },
-              {
-                "$ref": "#/components/schemas/ImageSize",
-                "description": "Size of the generated images."
-              }
-            ]
+          "client_secret": {
+            "type": [
+              "string",
+              "null"
+            ],
+            "description": "OAuth2 client secret (will be stored in secret manager)\nRequired for OIDC, not used for SAML"
           },
-          "stream": {
+          "create_users": {
+            "type": "boolean",
+            "description": "Whether to create new users on first login (default: true)"
+          },
+          "default_org_role": {
+            "type": "string",
+            "description": "Default role for new users in the organization (default: \"member\")"
+          },
+          "default_team_id": {
             "type": [
-              "boolean",
+              "string",
               "null"
             ],
-            "description": "Generate image in streaming mode. GPT image models only."
+            "format": "uuid",
+            "description": "Default team to add new users to (optional)"
           },
-          "style": {
-            "oneOf": [
-              {
-                "type": "null"
-              },
-              {
-                "$ref": "#/components/schemas/ImageStyle",
-                "description": "Image style. dall-e-3 only."
-              }
-            ]
+          "default_team_role": {
+            "type": "string",
+            "description": "Default role for new users in the default team (default: \"member\")"
+          },
+          "discovery_url": {
+            "type": [
+              "string",
+              "null"
+            ],
+            "description": "Discovery URL for OIDC metadata (optional - defaults to issuer/.well-known/openid-configuration)"
+          },
+          "enabled": {
+            "type": "boolean",
+            "description": "Whether this SSO config is active (default: true)"
+          },
+          "enforcement_mode": {
+            "$ref": "#/components/schemas/SsoEnforcementMode",
+            "description": "SSO enforcement mode (default: optional)"
           },
-          "user": {
+          "groups_claim": {
             "type": [
               "string",
               "null"
             ],
-            "description": "Unique identifier for the end-user for abuse detection."
-          }
-        }
-      },
-      "CreateImageVariationRequest": {
-        "type": "object",
-        "description": "Create image variation request (POST /v1/images/variations)\n\nNote: This endpoint accepts multipart/form-data. The `image` field\nis a file upload, not a JSON field.",
-        "properties": {
-          "model": {
+            "description": "JWT claim containing group memberships (optional)"
+          },
+          "identity_claim": {
+            "type": "string",
+            "description": "JWT claim to use as the user's identity (default: \"sub\")"
+          },
+          "issuer": {
             "type": [
               "string",
               "null"
             ],
-            "description": "The model to use. Only dall-e-2 is supported for variations."
+            "description": "OIDC issuer URL (e.g., \"https://accounts.google.com\")\nRequired for OIDC, not used for SAML"
           },
-          "n": {
+          "org_claim": {
             "type": [
-              "integer",
+              "string",
               "null"
             ],
-            "format": "int32",
-            "description": "Number of images to generate (1-10)."
+            "description": "JWT claim containing organization IDs (optional)"
           },
-          "response_format": {
-            "oneOf": [
-              {
-                "type": "null"
-              },
-              {
-                "$ref": "#/components/schemas/ImageResponseFormat",
-                "description": "Format for returning generated images (url or b64_json)."
-              }
-            ]
+          "provider_type": {
+            "$ref": "#/components/schemas/SsoProviderType",
+            "description": "Provider type (defaults to 'oidc')"
           },
-          "size": {
-            "oneOf": [
-              {
-                "type": "null"
-              },
-              {
-                "$ref": "#/components/schemas/ImageSize",
-                "description": "Size of the generated images."
-              }
-            ]
+          "provisioning_enabled": {
+            "type": "boolean",
+            "description": "Whether JIT provisioning is enabled (default: true)"
           },
-          "user": {
+          "redirect_uri": {
             "type": [
               "string",
               "null"
             ],
-            "description": "Unique identifier for the end-user for abuse detection."
-          }
-        }
-      },
-      "CreateModelPricing": {
-        "type": "object",
-        "description": "Request to create model pricing",
-        "required": [
-          "owner",
-          "provider",
-          "model"
-        ],
-        "properties": {
-          "cache_write_per_1m_tokens": {
+            "description": "Redirect URI for OAuth2 callback (optional - uses global default if not set)"
+          },
+          "saml_authn_context_class_ref": {
             "type": [
-              "integer",
+              "string",
               "null"
             ],
-            "format": "int64",
-            "description": "Cost per 1M cache write tokens in microcents"
+            "description": "Requested authentication context class"
           },
-          "cached_input_per_1m_tokens": {
+          "saml_email_attribute": {
             "type": [
-              "integer",
+              "string",
               "null"
             ],
-            "format": "int64",
-            "description": "Cost per 1M cached input tokens in microcents"
-          },
-          "input_per_1m_tokens": {
-            "type": "integer",
-            "format": "int64",
-            "description": "Cost per 1M input tokens in microcents"
-          },
-          "model": {
-            "type": "string"
-          },
-          "output_per_1m_tokens": {
-            "type": "integer",
-            "format": "int64",
-            "description": "Cost per 1M output tokens in microcents"
+            "description": "SAML attribute name for email"
           },
-          "owner": {
-            "$ref": "#/components/schemas/PricingOwner"
+          "saml_force_authn": {
+            "type": "boolean",
+            "description": "Whether to force re-authentication at IdP (default: false)"
           },
-          "per_1m_characters": {
+          "saml_groups_attribute": {
             "type": [
-              "integer",
+              "string",
               "null"
             ],
-            "format": "int64",
-            "description": "Cost per 1M characters in microcents (for TTS)"
+            "description": "SAML attribute name for groups"
           },
-          "per_image": {
+          "saml_identity_attribute": {
             "type": [
-              "integer",
+              "string",
               "null"
             ],
-            "format": "int64",
-            "description": "Cost per image in microcents"
+            "description": "SAML attribute name for user identity (like identity_claim for OIDC)"
           },
-          "per_request": {
+          "saml_idp_certificate": {
             "type": [
-              "integer",
+              "string",
               "null"
             ],
-            "format": "int64",
-            "description": "Cost per request in microcents"
+            "description": "IdP X.509 certificate for signature validation (PEM format)"
           },
-          "per_second": {
+          "saml_idp_entity_id": {
             "type": [
-              "integer",
+              "string",
               "null"
             ],
-            "format": "int64",
-            "description": "Cost per second of audio in microcents (for transcription/translation)"
-          },
-          "provider": {
-            "type": "string"
+            "description": "IdP entity identifier (e.g., \"https://idp.example.com/metadata\")"
           },
-          "reasoning_per_1m_tokens": {
+          "saml_idp_slo_url": {
             "type": [
-              "integer",
+              "string",
               "null"
             ],
-            "format": "int64",
-            "description": "Cost per 1M reasoning tokens in microcents"
+            "description": "IdP Single Logout service URL (optional)"
           },
-          "source": {
-            "$ref": "#/components/schemas/PricingSource"
-          }
-        }
-      },
-      "CreateOrgRbacPolicy": {
-        "type": "object",
-        "description": "Request to create a new organization RBAC policy.",
-        "required": [
-          "name",
-          "condition"
-        ],
-        "properties": {
-          "action": {
-            "type": "string",
-            "description": "Action pattern to match (e.g., \"read\", \"write\", \"delete\", \"*\")"
+          "saml_idp_sso_url": {
+            "type": [
+              "string",
+              "null"
+            ],
+            "description": "IdP Single Sign-On service URL (HTTP-Redirect or HTTP-POST binding)"
           },
-          "condition": {
-            "type": "string",
-            "description": "CEL expression that must evaluate to true for the policy to apply"
+          "saml_metadata_url": {
+            "type": [
+              "string",
+              "null"
+            ],
+            "description": "IdP metadata URL for auto-configuration (alternative to manual config)"
           },
-          "description": {
+          "saml_name_attribute": {
             "type": [
               "string",
               "null"
             ],
-            "description": "Optional description of what this policy does"
+            "description": "SAML attribute name for display name"
           },
-          "effect": {
-            "$ref": "#/components/schemas/RbacPolicyEffect",
-            "description": "Policy effect when condition matches (defaults to 'deny')"
+          "saml_name_id_format": {
+            "type": [
+              "string",
+              "null"
+            ],
+            "description": "NameID format to request (e.g., 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress')"
           },
-          "enabled": {
+          "saml_sign_requests": {
             "type": "boolean",
-            "description": "Whether this policy is active (defaults to true)"
+            "description": "Whether to sign AuthnRequests (default: false)"
           },
-          "name": {
-            "type": "string",
-            "description": "Human-readable name for this policy (unique per org)"
+          "saml_sp_certificate": {
+            "type": [
+              "string",
+              "null"
+            ],
+            "description": "SP X.509 certificate for metadata (PEM format)"
           },
-          "priority": {
-            "type": "integer",
-            "format": "int32",
-            "description": "Priority for evaluation order (higher = evaluated first, defaults to 0)\nValid range: -1000 to 1000"
+          "saml_sp_entity_id": {
+            "type": [
+              "string",
+              "null"
+            ],
+            "description": "Service Provider entity ID (Hadrian's identifier to the IdP)"
           },
-          "reason": {
+          "saml_sp_private_key": {
             "type": [
               "string",
               "null"
             ],
-            "description": "Reason for creating this policy (stored in version history)"
+            "description": "SP private key for signing AuthnRequests (PEM format, will be stored in secret manager)"
           },
-          "resource": {
-            "type": "string",
-            "description": "Resource pattern to match (e.g., \"projects/*\", \"teams/engineering/*\", \"*\")"
+          "scopes": {
+            "type": "array",
+            "items": {
+              "type": "string"
+            },
+            "description": "OAuth2 scopes to request (defaults to [\"openid\", \"email\", \"profile\"])"
+          },
+          "sync_attributes_on_login": {
+            "type": "boolean",
+            "description": "Whether to sync user attributes on each login (default: false)"
+          },
+          "sync_memberships_on_login": {
+            "type": "boolean",
+            "description": "Whether to sync team memberships from IdP groups on each login (default: true)"
           }
         }
       },
-      "CreateOrgScimConfig": {
+      "CreateOrganization": {
         "type": "object",
-        "description": "Request to create a new organization SCIM configuration.",
+        "required": [
+          "slug",
+          "name"
+        ],
         "properties": {
-          "create_users": {
-            "type": "boolean",
-            "description": "Whether to create new users when they don't exist (default: true)"
+          "name": {
+            "type": "string",
+            "description": "Display name"
           },
-          "deactivate_deletes_user": {
-            "type": "boolean",
-            "description": "Whether deactivating a user deletes them entirely (default: false)"
+          "slug": {
+            "type": "string",
+            "description": "URL-friendly identifier (lowercase alphanumeric with hyphens)"
+          }
+        }
+      },
+      "CreateProject": {
+        "type": "object",
+        "required": [
+          "slug",
+          "name"
+        ],
+        "properties": {
+          "name": {
+            "type": "string",
+            "description": "Display name"
           },
-          "default_org_role": {
+          "slug": {
             "type": "string",
-            "description": "Default role for new users in the organization (default: \"member\")"
+            "description": "URL-friendly identifier (lowercase alphanumeric with hyphens)"
           },
-          "default_team_id": {
+          "team_id": {
             "type": [
               "string",
               "null"
             ],
             "format": "uuid",
-            "description": "Default team to add new users to (optional)"
-          },
-          "default_team_role": {
-            "type": "string",
-            "description": "Default role for new users in the default team (default: \"member\")"
-          },
-          "enabled": {
-            "type": "boolean",
-            "description": "Whether SCIM provisioning is enabled (default: true)"
-          },
-          "revoke_api_keys_on_deactivate": {
-            "type": "boolean",
-            "description": "Whether to revoke all API keys when user is deactivated (default: true)"
-          },
-          "sync_display_name": {
-            "type": "boolean",
-            "description": "Whether to sync display name from SCIM on updates (default: true)"
+            "description": "Team to assign the project to (optional)"
           }
         }
       },
-      "CreateOrgSsoConfig": {
+      "CreateResponsesPayload": {
         "type": "object",
-        "description": "Request to create a new organization SSO configuration.",
+        "description": "Create responses request (OpenAI Responses API)",
         "properties": {
-          "allowed_email_domains": {
+          "background": {
+            "type": [
+              "boolean",
+              "null"
+            ],
+            "description": "Run in background"
+          },
+          "frequency_penalty": {
+            "type": [
+              "number",
+              "null"
+            ],
+            "format": "double",
+            "description": "**Hadrian Extension:** Frequency penalty (-2.0 to 2.0)"
+          },
+          "include": {
             "type": "array",
             "items": {
               "type": "string"
             },
-            "description": "Allowed email domains (empty = allow all)"
+            "description": "Items to include in response"
           },
-          "client_id": {
+          "input": {
+            "type": "object",
+            "description": "Input messages/items"
+          },
+          "instructions": {
             "type": [
               "string",
               "null"
             ],
-            "description": "OAuth2 client ID (required for OIDC, not used for SAML)"
+            "description": "System instructions"
           },
-          "client_secret": {
+          "max_output_tokens": {
             "type": [
-              "string",
+              "number",
               "null"
             ],
-            "description": "OAuth2 client secret (will be stored in secret manager)\nRequired for OIDC, not used for SAML"
-          },
-          "create_users": {
-            "type": "boolean",
-            "description": "Whether to create new users on first login (default: true)"
+            "format": "double",
+            "description": "Maximum output tokens"
           },
-          "default_org_role": {
-            "type": "string",
-            "description": "Default role for new users in the organization (default: \"member\")"
+          "metadata": {
+            "type": "object",
+            "description": "Request metadata"
           },
-          "default_team_id": {
+          "model": {
             "type": [
               "string",
               "null"
             ],
-            "format": "uuid",
-            "description": "Default team to add new users to (optional)"
-          },
-          "default_team_role": {
-            "type": "string",
-            "description": "Default role for new users in the default team (default: \"member\")"
+            "description": "Model to use"
           },
-          "discovery_url": {
+          "models": {
             "type": [
-              "string",
+              "array",
               "null"
             ],
-            "description": "Discovery URL for OIDC metadata (optional - defaults to issuer/.well-known/openid-configuration)"
-          },
-          "enabled": {
-            "type": "boolean",
-            "description": "Whether this SSO config is active (default: true)"
-          },
-          "enforcement_mode": {
-            "$ref": "#/components/schemas/SsoEnforcementMode",
-            "description": "SSO enforcement mode (default: optional)"
+            "items": {
+              "type": "string"
+            },
+            "description": "**Hadrian Extension:** List of models for multi-model routing (alternative to single model)"
           },
-          "groups_claim": {
+          "parallel_tool_calls": {
             "type": [
-              "string",
+              "boolean",
               "null"
             ],
-            "description": "JWT claim containing group memberships (optional)"
+            "description": "Allow parallel tool calls"
           },
-          "identity_claim": {
-            "type": "string",
-            "description": "JWT claim to use as the user's identity (default: \"sub\")"
+          "plugins": {
+            "type": "array",
+            "items": {
+              "type": "object"
+            },
+            "description": "**Hadrian Extension:** Plugins to enable for this request"
           },
-          "issuer": {
+          "presence_penalty": {
             "type": [
-              "string",
+              "number",
               "null"
             ],
-            "description": "OIDC issuer URL (e.g., \"https://accounts.google.com\")\nRequired for OIDC, not used for SAML"
+            "format": "double",
+            "description": "**Hadrian Extension:** Presence penalty (-2.0 to 2.0)"
           },
-          "org_claim": {
+          "previous_response_id": {
             "type": [
               "string",
               "null"
             ],
-            "description": "JWT claim containing organization IDs (optional)"
-          },
-          "provider_type": {
-            "$ref": "#/components/schemas/SsoProviderType",
-            "description": "Provider type (defaults to 'oidc')"
+            "description": "Previous response ID for conversation continuation"
           },
-          "provisioning_enabled": {
-            "type": "boolean",
-            "description": "Whether JIT provisioning is enabled (default: true)"
+          "prompt": {
+            "type": "object",
+            "description": "Prompt template reference"
           },
-          "redirect_uri": {
+          "prompt_cache_key": {
             "type": [
               "string",
               "null"
             ],
-            "description": "Redirect URI for OAuth2 callback (optional - uses global default if not set)"
+            "description": "Prompt cache key"
           },
-          "saml_authn_context_class_ref": {
+          "provider": {
+            "type": "object",
+            "description": "**Hadrian Extension:** Provider routing configuration"
+          },
+          "reasoning": {
+            "type": "object",
+            "description": "Reasoning configuration"
+          },
+          "safety_identifier": {
             "type": [
               "string",
               "null"
             ],
-            "description": "Requested authentication context class"
+            "description": "Safety identifier"
           },
-          "saml_email_attribute": {
+          "service_tier": {
+            "type": "object",
+            "description": "Service tier"
+          },
+          "sovereignty_requirements": {
+            "oneOf": [
+              {
+                "type": "null"
+              },
+              {
+                "$ref": "#/components/schemas/SovereigntyRequirements",
+                "description": "**Hadrian Extension:** Per-request sovereignty requirements.\nMerged with API key requirements (most restrictive wins)."
+              }
+            ]
+          },
+          "store": {
             "type": [
-              "string",
+              "boolean",
               "null"
             ],
-            "description": "SAML attribute name for email"
+            "description": "Store response"
           },
-          "saml_force_authn": {
+          "stream": {
             "type": "boolean",
-            "description": "Whether to force re-authentication at IdP (default: false)"
+            "description": "Enable streaming"
           },
-          "saml_groups_attribute": {
+          "temperature": {
             "type": [
-              "string",
+              "number",
               "null"
             ],
-            "description": "SAML attribute name for groups"
+            "format": "double",
+            "description": "Sampling temperature (0.0 to 2.0)"
           },
-          "saml_identity_attribute": {
+          "text": {
+            "type": "object",
+            "description": "Text configuration"
+          },
+          "tool_choice": {
+            "type": "object",
+            "description": "Tool choice configuration"
+          },
+          "tools": {
+            "type": "array",
+            "items": {
+              "type": "object"
+            },
+            "description": "Available tools"
+          },
+          "top_k": {
             "type": [
-              "string",
+              "number",
               "null"
             ],
-            "description": "SAML attribute name for user identity (like identity_claim for OIDC)"
+            "format": "double",
+            "description": "**Hadrian Extension:** Top-k sampling (supported by some providers like Anthropic)"
           },
-          "saml_idp_certificate": {
+          "top_p": {
             "type": [
-              "string",
+              "number",
               "null"
             ],
-            "description": "IdP X.509 certificate for signature validation (PEM format)"
+            "format": "double",
+            "description": "Nucleus sampling probability (0.0 to 1.0)"
           },
-          "saml_idp_entity_id": {
+          "truncation": {
+            "type": "object",
+            "description": "Truncation strategy"
+          },
+          "user": {
             "type": [
               "string",
               "null"
             ],
-            "description": "IdP entity identifier (e.g., \"https://idp.example.com/metadata\")"
+            "description": "User identifier for abuse detection"
+          }
+        }
+      },
+      "CreateSelfServiceApiKey": {
+        "type": "object",
+        "description": "Self-service API key creation request (owner auto-set to current user).",
+        "required": [
+          "name"
+        ],
+        "properties": {
+          "allowed_models": {
+            "type": [
+              "array",
+              "null"
+            ],
+            "items": {
+              "type": "string"
+            },
+            "description": "Allowed models (null = all models)"
           },
-          "saml_idp_slo_url": {
+          "budget_limit_cents": {
             "type": [
-              "string",
+              "integer",
               "null"
             ],
-            "description": "IdP Single Logout service URL (optional)"
+            "format": "int64",
+            "description": "Budget limit in cents"
           },
-          "saml_idp_sso_url": {
+          "budget_period": {
+            "oneOf": [
+              {
+                "type": "null"
+              },
+              {
+                "$ref": "#/components/schemas/BudgetPeriod"
+              }
+            ]
+          },
+          "expires_at": {
             "type": [
               "string",
               "null"
             ],
-            "description": "IdP Single Sign-On service URL (HTTP-Redirect or HTTP-POST binding)"
+            "format": "date-time"
           },
-          "saml_metadata_url": {
+          "ip_allowlist": {
             "type": [
-              "string",
+              "array",
               "null"
             ],
-            "description": "IdP metadata URL for auto-configuration (alternative to manual config)"
+            "items": {
+              "type": "string"
+            },
+            "description": "IP allowlist in CIDR notation (null = all IPs)"
           },
-          "saml_name_attribute": {
+          "name": {
+            "type": "string"
+          },
+          "rate_limit_rpm": {
             "type": [
-              "string",
+              "integer",
               "null"
             ],
-            "description": "SAML attribute name for display name"
+            "format": "int32",
+            "description": "Requests per minute override"
           },
-          "saml_name_id_format": {
+          "rate_limit_tpm": {
             "type": [
-              "string",
+              "integer",
               "null"
             ],
-            "description": "NameID format to request (e.g., 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress')"
-          },
-          "saml_sign_requests": {
-            "type": "boolean",
-            "description": "Whether to sign AuthnRequests (default: false)"
+            "format": "int32",
+            "description": "Tokens per minute override"
           },
-          "saml_sp_certificate": {
+          "scopes": {
             "type": [
-              "string",
+              "array",
               "null"
             ],
-            "description": "SP X.509 certificate for metadata (PEM format)"
+            "items": {
+              "type": "string"
+            },
+            "description": "Permission scopes (null = full access)"
           },
-          "saml_sp_entity_id": {
+          "sovereignty_requirements": {
+            "oneOf": [
+              {
+                "type": "null"
+              },
+              {
+                "$ref": "#/components/schemas/SovereigntyRequirements",
+                "description": "Sovereignty requirements for model access"
+              }
+            ]
+          }
+        }
+      },
+      "CreateSelfServiceProvider": {
+        "type": "object",
+        "description": "Self-service create DTO (owner is inferred from the authenticated user)",
+        "required": [
+          "name",
+          "provider_type"
+        ],
+        "properties": {
+          "api_key": {
             "type": [
               "string",
               "null"
             ],
-            "description": "Service Provider entity ID (Hadrian's identifier to the IdP)"
+            "description": "Raw API key (stored in secrets manager if available, otherwise stored directly)"
           },
-          "saml_sp_private_key": {
+          "base_url": {
+            "type": "string",
+            "description": "Base URL for the provider (required for OpenAI/Anthropic/Azure, optional for Bedrock/Vertex)"
+          },
+          "config": {
+            "description": "Provider-specific configuration (e.g., region, credentials for Bedrock/Vertex)"
+          },
+          "models": {
             "type": [
-              "string",
+              "array",
               "null"
             ],
-            "description": "SP private key for signing AuthnRequests (PEM format, will be stored in secret manager)"
-          },
-          "scopes": {
-            "type": "array",
             "items": {
               "type": "string"
             },
-            "description": "OAuth2 scopes to request (defaults to [\"openid\", \"email\", \"profile\"])"
+            "description": "List of supported model names"
           },
-          "sync_attributes_on_login": {
-            "type": "boolean",
-            "description": "Whether to sync user attributes on each login (default: false)"
+          "name": {
+            "type": "string"
           },
-          "sync_memberships_on_login": {
-            "type": "boolean",
-            "description": "Whether to sync team memberships from IdP groups on each login (default: true)"
+          "provider_type": {
+            "type": "string",
+            "description": "Provider type (e.g., \"openai\", \"anthropic\", \"bedrock\", \"vertex\")"
+          },
+          "sovereignty": {
+            "oneOf": [
+              {
+                "type": "null"
+              },
+              {
+                "$ref": "#/components/schemas/SovereigntyMetadata",
+                "description": "Sovereignty and compliance metadata"
+              }
+            ]
           }
         }
       },
-      "CreateOrganization": {
+      "CreateServiceAccount": {
         "type": "object",
+        "description": "Request to create a new service account",
         "required": [
           "slug",
           "name"
         ],
         "properties": {
+          "description": {
+            "type": [
+              "string",
+              "null"
+            ],
+            "description": "Optional description"
+          },
           "name": {
             "type": "string",
             "description": "Display name"
           },
+          "roles": {
+            "type": "array",
+            "items": {
+              "type": "string"
+            },
+            "description": "Roles to assign (freeform strings, defaults to empty)"
+          },
           "slug": {
             "type": "string",
             "description": "URL-friendly identifier (lowercase alphanumeric with hyphens)"
           }
         }
       },
-      "CreateProject": {
+      "CreateSpeechRequest": {
         "type": "object",
+        "description": "Create speech request (POST /v1/audio/speech)",
         "required": [
-          "slug",
-          "name"
+          "model",
+          "input",
+          "voice"
         ],
         "properties": {
-          "name": {
+          "input": {
             "type": "string",
-            "description": "Display name"
+            "description": "The text to generate audio for. Maximum length is 4096 characters."
           },
-          "slug": {
+          "instructions": {
+            "type": [
+              "string",
+              "null"
+            ],
+            "description": "Control the voice with additional instructions. Does not work with tts-1 or tts-1-hd."
+          },
+          "model": {
             "type": "string",
-            "description": "URL-friendly identifier (lowercase alphanumeric with hyphens)"
+            "description": "One of the available TTS models: tts-1, tts-1-hd, or gpt-4o-mini-tts."
+          },
+          "response_format": {
+            "oneOf": [
+              {
+                "type": "null"
+              },
+              {
+                "$ref": "#/components/schemas/SpeechResponseFormat",
+                "description": "The format of the audio output."
+              }
+            ]
+          },
+          "sovereignty_requirements": {
+            "oneOf": [
+              {
+                "type": "null"
+              },
+              {
+                "$ref": "#/components/schemas/SovereigntyRequirements",
+                "description": "**Hadrian Extension:** Per-request sovereignty requirements.\nMerged with API key requirements (most restrictive wins)."
+              }
+            ]
+          },
+          "speed": {
+            "type": [
+              "number",
+              "null"
+            ],
+            "format": "float",
+            "description": "The speed of the generated audio. Select a value from 0.25 to 4.0. Default is 1.0."
+          },
+          "stream_format": {
+            "oneOf": [
+              {
+                "type": "null"
+              },
+              {
+                "$ref": "#/components/schemas/SpeechStreamFormat",
+                "description": "The format to stream the audio in. Supported formats are sse and audio."
+              }
+            ]
+          },
+          "voice": {
+            "$ref": "#/components/schemas/Voice",
+            "description": "The voice to use when generating the audio."
+          }
+        }
+      },
+      "CreateSsoGroupMapping": {
+        "type": "object",
+        "description": "Request to create a new SSO group mapping.",
+        "required": [
+          "idp_group"
+        ],
+        "properties": {
+          "idp_group": {
+            "type": "string",
+            "description": "The IdP group name exactly as it appears in the groups claim"
+          },
+          "priority": {
+            "type": "integer",
+            "format": "int32",
+            "description": "Priority for role precedence (higher = wins when multiple mappings target same team)\nDefaults to 0 if not specified."
+          },
+          "role": {
+            "type": [
+              "string",
+              "null"
+            ],
+            "description": "Role to assign (within the team if team_id is set, otherwise org-level role)"
+          },
+          "sso_connection_name": {
+            "type": "string",
+            "description": "Which SSO connection this mapping applies to (defaults to 'default')"
           },
           "team_id": {
             "type": [
@@ -15886,13 +21977,30 @@
               "null"
             ],
             "format": "uuid",
-            "description": "Team to assign the project to (optional)"
+            "description": "Team to add users to when they have this IdP group (optional)"
+          }
+        }
+      },
+      "CreateTeam": {
+        "type": "object",
+        "required": [
+          "slug",
+          "name"
+        ],
+        "properties": {
+          "name": {
+            "type": "string",
+            "description": "Display name"
+          },
+          "slug": {
+            "type": "string",
+            "description": "URL-friendly identifier (lowercase alphanumeric with hyphens)"
           }
         }
       },
-      "CreatePrompt": {
+      "CreateTemplate": {
         "type": "object",
-        "description": "Request to create a new prompt",
+        "description": "Request to create a new template",
         "required": [
           "owner",
           "name",
@@ -15901,7 +22009,7 @@
         "properties": {
           "content": {
             "type": "string",
-            "description": "The actual prompt content"
+            "description": "The actual template content"
           },
           "description": {
             "type": [
@@ -15923,667 +22031,839 @@
           },
           "name": {
             "type": "string",
-            "description": "Name of the prompt template (unique per owner)"
+            "description": "Name of the template (unique per owner)"
           },
           "owner": {
-            "$ref": "#/components/schemas/PromptOwner",
-            "description": "Owner of the prompt"
+            "$ref": "#/components/schemas/TemplateOwner",
+            "description": "Owner of the template"
           }
         }
       },
-      "CreateResponsesPayload": {
+      "CreateTranscriptionRequest": {
         "type": "object",
-        "description": "Create responses request (OpenAI Responses API)",
+        "description": "Create transcription request (POST /v1/audio/transcriptions)\n\nNote: This endpoint accepts multipart/form-data. The `file` field\nis a file upload, not a JSON field.",
+        "required": [
+          "model"
+        ],
         "properties": {
-          "background": {
+          "chunking_strategy": {
+            "oneOf": [
+              {
+                "type": "null"
+              },
+              {
+                "$ref": "#/components/schemas/TranscriptionChunkingStrategy",
+                "description": "Chunking strategy for the transcription."
+              }
+            ]
+          },
+          "include": {
+            "type": [
+              "array",
+              "null"
+            ],
+            "items": {
+              "$ref": "#/components/schemas/TranscriptionInclude"
+            },
+            "description": "Additional information to include in the response."
+          },
+          "known_speaker_names": {
+            "type": [
+              "array",
+              "null"
+            ],
+            "items": {
+              "type": "string"
+            },
+            "description": "Speaker names corresponding to known_speaker_references. Up to 4 speakers."
+          },
+          "known_speaker_references": {
             "type": [
-              "boolean",
+              "array",
               "null"
             ],
-            "description": "Run in background"
-          },
-          "include": {
-            "type": "array",
             "items": {
               "type": "string"
             },
-            "description": "Items to include in response"
-          },
-          "input": {
-            "type": "object",
-            "description": "Input messages/items"
+            "description": "Audio samples as data URLs for known speaker references. 2-10 seconds each."
           },
-          "instructions": {
+          "language": {
             "type": [
               "string",
               "null"
             ],
-            "description": "System instructions"
+            "description": "The language of the input audio in ISO-639-1 format (e.g., \"en\").\nSupplying the input language improves accuracy and latency."
           },
-          "max_output_tokens": {
+          "model": {
+            "type": "string",
+            "description": "ID of the model to use. Options: gpt-4o-transcribe, gpt-4o-mini-transcribe,\nwhisper-1, gpt-4o-transcribe-diarize."
+          },
+          "prompt": {
             "type": [
-              "number",
+              "string",
               "null"
             ],
-            "format": "double",
-            "description": "Maximum output tokens"
+            "description": "Optional text to guide the model's style or continue a previous audio segment.\nThe prompt should match the audio language."
           },
-          "metadata": {
-            "type": "object",
-            "description": "Request metadata"
+          "response_format": {
+            "oneOf": [
+              {
+                "type": "null"
+              },
+              {
+                "$ref": "#/components/schemas/AudioResponseFormat",
+                "description": "The format of the output."
+              }
+            ]
           },
-          "model": {
+          "stream": {
             "type": [
-              "string",
+              "boolean",
               "null"
             ],
-            "description": "Model to use"
+            "description": "If true, stream the response using server-sent events.\nNot supported for whisper-1."
           },
-          "models": {
+          "temperature": {
             "type": [
-              "array",
+              "number",
               "null"
             ],
-            "items": {
-              "type": "string"
-            },
-            "description": "**Hadrian Extension:** List of models for multi-model routing (alternative to single model)"
+            "format": "float",
+            "description": "The sampling temperature, between 0 and 1."
           },
-          "parallel_tool_calls": {
+          "timestamp_granularities": {
             "type": [
-              "boolean",
+              "array",
               "null"
             ],
-            "description": "Allow parallel tool calls"
-          },
-          "plugins": {
-            "type": "array",
             "items": {
-              "type": "object"
+              "$ref": "#/components/schemas/TimestampGranularity"
             },
-            "description": "**Hadrian Extension:** Plugins to enable for this request"
+            "description": "The timestamp granularities to populate. Requires response_format=verbose_json."
+          }
+        }
+      },
+      "CreateTranslationRequest": {
+        "type": "object",
+        "description": "Create translation request (POST /v1/audio/translations)\n\nNote: This endpoint accepts multipart/form-data. The `file` field\nis a file upload, not a JSON field.",
+        "required": [
+          "model"
+        ],
+        "properties": {
+          "model": {
+            "type": "string",
+            "description": "ID of the model to use. Only whisper-1 is currently available."
           },
-          "previous_response_id": {
+          "prompt": {
             "type": [
               "string",
               "null"
             ],
-            "description": "Previous response ID for conversation continuation"
+            "description": "Optional text to guide the model's style or continue a previous audio segment.\nThe prompt should be in English."
           },
-          "prompt": {
-            "type": "object",
-            "description": "Prompt template reference"
+          "response_format": {
+            "oneOf": [
+              {
+                "type": "null"
+              },
+              {
+                "$ref": "#/components/schemas/AudioResponseFormat",
+                "description": "The format of the output."
+              }
+            ]
           },
-          "prompt_cache_key": {
+          "temperature": {
             "type": [
-              "string",
+              "number",
               "null"
             ],
-            "description": "Prompt cache key"
-          },
-          "provider": {
-            "type": "object",
-            "description": "**Hadrian Extension:** Provider routing configuration"
-          },
-          "reasoning": {
-            "type": "object",
-            "description": "Reasoning configuration"
-          },
-          "safety_identifier": {
+            "format": "float",
+            "description": "The sampling temperature, between 0 and 1."
+          }
+        }
+      },
+      "CreateUser": {
+        "type": "object",
+        "required": [
+          "external_id"
+        ],
+        "properties": {
+          "email": {
             "type": [
               "string",
               "null"
-            ],
-            "description": "Safety identifier"
+            ]
           },
-          "service_tier": {
-            "type": "object",
-            "description": "Service tier"
+          "external_id": {
+            "type": "string",
+            "description": "External identifier (e.g., from SSO provider)"
           },
-          "store": {
+          "name": {
             "type": [
-              "boolean",
+              "string",
               "null"
-            ],
-            "description": "Store response"
-          },
-          "stream": {
-            "type": "boolean",
-            "description": "Enable streaming"
+            ]
+          }
+        }
+      },
+      "CreateVectorStore": {
+        "type": "object",
+        "description": "Request to create a new vector store.\n\n## Hadrian Extensions\n\nThe following fields are **Hadrian extensions** not present in the standard OpenAI API:\n- `owner`: Multi-tenancy support (required, specifies organization/project/user ownership)\n- `embedding_model`: Custom embedding model selection (default: text-embedding-3-small)\n- `embedding_dimensions`: Custom embedding dimensions (default: 1536)\n\n## OpenAI Compatibility Notes\n\n- `name` is optional (OpenAI-compatible), but a name will be auto-generated if not provided",
+        "required": [
+          "owner"
+        ],
+        "properties": {
+          "chunking_strategy": {
+            "oneOf": [
+              {
+                "type": "null"
+              },
+              {
+                "$ref": "#/components/schemas/ChunkingStrategy",
+                "description": "The chunking strategy used to chunk the file(s). If not set, will use the `auto` strategy.\nOnly applicable if `file_ids` is non-empty."
+              }
+            ]
           },
-          "temperature": {
+          "description": {
             "type": [
-              "number",
+              "string",
               "null"
             ],
-            "format": "double",
-            "description": "Sampling temperature (0.0 to 2.0)"
+            "description": "Description of the vector store"
           },
-          "text": {
-            "type": "object",
-            "description": "Text configuration"
+          "embedding_dimensions": {
+            "type": "integer",
+            "format": "int32",
+            "description": "**Hadrian Extension:** Embedding dimensions (immutable after creation, default: 1536)"
           },
-          "tool_choice": {
-            "type": "object",
-            "description": "Tool choice configuration"
+          "embedding_model": {
+            "type": "string",
+            "description": "**Hadrian Extension:** Embedding model to use (immutable after creation, default: text-embedding-3-small)"
           },
-          "tools": {
+          "expires_after": {
+            "oneOf": [
+              {
+                "type": "null"
+              },
+              {
+                "$ref": "#/components/schemas/ExpiresAfter",
+                "description": "Expiration policy"
+              }
+            ]
+          },
+          "file_ids": {
             "type": "array",
             "items": {
-              "type": "object"
+              "type": "string",
+              "format": "uuid"
             },
-            "description": "Available tools"
+            "description": "A list of File IDs that the vector store should use (max 500).\nFiles will be attached to the vector store after creation."
           },
-          "top_k": {
+          "metadata": {
             "type": [
-              "number",
+              "object",
               "null"
             ],
-            "format": "double",
-            "description": "**Hadrian Extension:** Top-k sampling (supported by some providers like Anthropic)"
+            "description": "Custom metadata (up to 16 key-value pairs, keys max 64 chars, string values max 512 chars)",
+            "additionalProperties": {},
+            "propertyNames": {
+              "type": "string"
+            }
           },
-          "top_p": {
+          "name": {
             "type": [
-              "number",
+              "string",
               "null"
             ],
-            "format": "double",
-            "description": "Nucleus sampling probability (0.0 to 1.0)"
+            "description": "Name of the vector store (optional, auto-generated if not provided)"
+          },
+          "owner": {
+            "$ref": "#/components/schemas/VectorStoreOwner",
+            "description": "**Hadrian Extension:** Owner of the vector store (required for multi-tenancy)"
+          }
+        }
+      },
+      "CreateVectorStoreFileRequest": {
+        "type": "object",
+        "description": "Request to add a file to a vector store",
+        "required": [
+          "file_id"
+        ],
+        "properties": {
+          "chunking_strategy": {
+            "oneOf": [
+              {
+                "type": "null"
+              },
+              {
+                "$ref": "#/components/schemas/ChunkingStrategy",
+                "description": "Chunking strategy for processing the file"
+              }
+            ]
+          },
+          "file_id": {
+            "type": "string",
+            "description": "The ID of the file to add (from the Files API)",
+            "example": "file-550e8400-e29b-41d4-a716-446655440000"
+          }
+        }
+      },
+      "CreatedApiKey": {
+        "allOf": [
+          {
+            "$ref": "#/components/schemas/ApiKey"
           },
-          "truncation": {
+          {
             "type": "object",
-            "description": "Truncation strategy"
-          },
-          "user": {
-            "type": [
-              "string",
-              "null"
+            "required": [
+              "key"
             ],
-            "description": "User identifier for abuse detection"
+            "properties": {
+              "key": {
+                "type": "string",
+                "description": "The raw API key (only shown once at creation)"
+              }
+            }
           }
-        }
+        ],
+        "description": "Returned on creation only (contains the raw key)"
       },
-      "CreateServiceAccount": {
+      "CreatedOrgScimConfig": {
         "type": "object",
-        "description": "Request to create a new service account",
+        "description": "Result of creating a new SCIM config (includes the raw token, shown only once)",
         "required": [
-          "slug",
-          "name"
+          "config",
+          "token"
         ],
         "properties": {
-          "description": {
-            "type": [
-              "string",
-              "null"
-            ],
-            "description": "Optional description"
-          },
-          "name": {
-            "type": "string",
-            "description": "Display name"
-          },
-          "roles": {
-            "type": "array",
-            "items": {
-              "type": "string"
-            },
-            "description": "Roles to assign (freeform strings, defaults to empty)"
+          "config": {
+            "$ref": "#/components/schemas/OrgScimConfig",
+            "description": "The created SCIM configuration"
           },
-          "slug": {
+          "token": {
             "type": "string",
-            "description": "URL-friendly identifier (lowercase alphanumeric with hyphens)"
+            "description": "The raw SCIM bearer token (only shown once at creation time!)\nFormat: \"scim_<random_base64>\" (e.g., \"scim_Abc123XyzDef456...\")"
           }
         }
       },
-      "CreateSpeechRequest": {
+      "DailyModelSpendResponse": {
         "type": "object",
-        "description": "Create speech request (POST /v1/audio/speech)",
+        "description": "Daily usage breakdown by model",
         "required": [
+          "date",
           "model",
-          "input",
-          "voice"
+          "total_cost",
+          "input_tokens",
+          "output_tokens",
+          "total_tokens",
+          "request_count",
+          "image_count",
+          "audio_seconds",
+          "character_count"
         ],
         "properties": {
-          "input": {
+          "audio_seconds": {
+            "type": "integer",
+            "format": "int64",
+            "description": "**Hadrian Extension:** Audio duration in seconds"
+          },
+          "character_count": {
+            "type": "integer",
+            "format": "int64",
+            "description": "**Hadrian Extension:** Character count (TTS input)"
+          },
+          "date": {
             "type": "string",
-            "description": "The text to generate audio for. Maximum length is 4096 characters."
+            "description": "Date (YYYY-MM-DD)"
           },
-          "instructions": {
-            "type": [
-              "string",
-              "null"
-            ],
-            "description": "Control the voice with additional instructions. Does not work with tts-1 or tts-1-hd."
+          "image_count": {
+            "type": "integer",
+            "format": "int64",
+            "description": "**Hadrian Extension:** Number of images generated"
+          },
+          "input_tokens": {
+            "type": "integer",
+            "format": "int64",
+            "description": "Input tokens used"
           },
           "model": {
             "type": "string",
-            "description": "One of the available TTS models: tts-1, tts-1-hd, or gpt-4o-mini-tts."
+            "description": "Model name"
           },
-          "response_format": {
-            "oneOf": [
-              {
-                "type": "null"
-              },
-              {
-                "$ref": "#/components/schemas/SpeechResponseFormat",
-                "description": "The format of the audio output."
-              }
-            ]
+          "output_tokens": {
+            "type": "integer",
+            "format": "int64",
+            "description": "Output tokens used"
           },
-          "speed": {
-            "type": [
-              "number",
-              "null"
-            ],
-            "format": "float",
-            "description": "The speed of the generated audio. Select a value from 0.25 to 4.0. Default is 1.0."
+          "request_count": {
+            "type": "integer",
+            "format": "int64",
+            "description": "Number of requests"
           },
-          "stream_format": {
-            "oneOf": [
-              {
-                "type": "null"
-              },
-              {
-                "$ref": "#/components/schemas/SpeechStreamFormat",
-                "description": "The format to stream the audio in. Supported formats are sse and audio."
-              }
-            ]
+          "total_cost": {
+            "type": "number",
+            "format": "double",
+            "description": "Total cost in dollars for this day/model"
           },
-          "voice": {
-            "$ref": "#/components/schemas/Voice",
-            "description": "The voice to use when generating the audio."
+          "total_tokens": {
+            "type": "integer",
+            "format": "int64",
+            "description": "Total tokens used"
           }
         }
       },
-      "CreateSsoGroupMapping": {
+      "DailyOrgSpendResponse": {
         "type": "object",
-        "description": "Request to create a new SSO group mapping.",
+        "description": "Daily usage breakdown by organization",
         "required": [
-          "idp_group"
+          "date",
+          "total_cost",
+          "input_tokens",
+          "output_tokens",
+          "total_tokens",
+          "request_count",
+          "image_count",
+          "audio_seconds",
+          "character_count"
         ],
         "properties": {
-          "idp_group": {
-            "type": "string",
-            "description": "The IdP group name exactly as it appears in the groups claim"
+          "audio_seconds": {
+            "type": "integer",
+            "format": "int64"
           },
-          "priority": {
+          "character_count": {
             "type": "integer",
-            "format": "int32",
-            "description": "Priority for role precedence (higher = wins when multiple mappings target same team)\nDefaults to 0 if not specified."
+            "format": "int64"
           },
-          "role": {
+          "date": {
+            "type": "string"
+          },
+          "image_count": {
+            "type": "integer",
+            "format": "int64"
+          },
+          "input_tokens": {
+            "type": "integer",
+            "format": "int64"
+          },
+          "org_id": {
             "type": [
               "string",
               "null"
-            ],
-            "description": "Role to assign (within the team if team_id is set, otherwise org-level role)"
-          },
-          "sso_connection_name": {
-            "type": "string",
-            "description": "Which SSO connection this mapping applies to (defaults to 'default')"
+            ]
           },
-          "team_id": {
+          "org_name": {
             "type": [
               "string",
               "null"
-            ],
-            "format": "uuid",
-            "description": "Team to add users to when they have this IdP group (optional)"
+            ]
+          },
+          "output_tokens": {
+            "type": "integer",
+            "format": "int64"
+          },
+          "request_count": {
+            "type": "integer",
+            "format": "int64"
+          },
+          "total_cost": {
+            "type": "number",
+            "format": "double"
+          },
+          "total_tokens": {
+            "type": "integer",
+            "format": "int64"
           }
         }
       },
-      "CreateTeam": {
+      "DailyPricingSourceSpendResponse": {
         "type": "object",
+        "description": "Daily usage breakdown by pricing source",
         "required": [
-          "slug",
-          "name"
+          "date",
+          "pricing_source",
+          "total_cost",
+          "input_tokens",
+          "output_tokens",
+          "total_tokens",
+          "request_count",
+          "image_count",
+          "audio_seconds",
+          "character_count"
         ],
         "properties": {
-          "name": {
+          "audio_seconds": {
+            "type": "integer",
+            "format": "int64",
+            "description": "**Hadrian Extension:** Audio duration in seconds"
+          },
+          "character_count": {
+            "type": "integer",
+            "format": "int64",
+            "description": "**Hadrian Extension:** Character count (TTS input)"
+          },
+          "date": {
             "type": "string",
-            "description": "Display name"
+            "description": "Date (YYYY-MM-DD)"
           },
-          "slug": {
+          "image_count": {
+            "type": "integer",
+            "format": "int64",
+            "description": "**Hadrian Extension:** Number of images generated"
+          },
+          "input_tokens": {
+            "type": "integer",
+            "format": "int64",
+            "description": "Input tokens"
+          },
+          "output_tokens": {
+            "type": "integer",
+            "format": "int64",
+            "description": "Output tokens"
+          },
+          "pricing_source": {
             "type": "string",
-            "description": "URL-friendly identifier (lowercase alphanumeric with hyphens)"
+            "description": "Pricing source"
+          },
+          "request_count": {
+            "type": "integer",
+            "format": "int64",
+            "description": "Number of requests"
+          },
+          "total_cost": {
+            "type": "number",
+            "format": "double",
+            "description": "Total cost in dollars for this day/pricing source"
+          },
+          "total_tokens": {
+            "type": "integer",
+            "format": "int64",
+            "description": "Total tokens"
           }
         }
       },
-      "CreateTranscriptionRequest": {
+      "DailyProjectSpendResponse": {
         "type": "object",
-        "description": "Create transcription request (POST /v1/audio/transcriptions)\n\nNote: This endpoint accepts multipart/form-data. The `file` field\nis a file upload, not a JSON field.",
+        "description": "Daily usage breakdown by project",
         "required": [
-          "model"
+          "date",
+          "total_cost",
+          "input_tokens",
+          "output_tokens",
+          "total_tokens",
+          "request_count",
+          "image_count",
+          "audio_seconds",
+          "character_count"
         ],
         "properties": {
-          "chunking_strategy": {
-            "oneOf": [
-              {
-                "type": "null"
-              },
-              {
-                "$ref": "#/components/schemas/TranscriptionChunkingStrategy",
-                "description": "Chunking strategy for the transcription."
-              }
-            ]
+          "audio_seconds": {
+            "type": "integer",
+            "format": "int64"
           },
-          "include": {
-            "type": [
-              "array",
-              "null"
-            ],
-            "items": {
-              "$ref": "#/components/schemas/TranscriptionInclude"
-            },
-            "description": "Additional information to include in the response."
+          "character_count": {
+            "type": "integer",
+            "format": "int64"
           },
-          "known_speaker_names": {
-            "type": [
-              "array",
-              "null"
-            ],
-            "items": {
-              "type": "string"
-            },
-            "description": "Speaker names corresponding to known_speaker_references. Up to 4 speakers."
+          "date": {
+            "type": "string"
           },
-          "known_speaker_references": {
-            "type": [
-              "array",
-              "null"
-            ],
-            "items": {
-              "type": "string"
-            },
-            "description": "Audio samples as data URLs for known speaker references. 2-10 seconds each."
+          "image_count": {
+            "type": "integer",
+            "format": "int64"
           },
-          "language": {
-            "type": [
-              "string",
-              "null"
-            ],
-            "description": "The language of the input audio in ISO-639-1 format (e.g., \"en\").\nSupplying the input language improves accuracy and latency."
+          "input_tokens": {
+            "type": "integer",
+            "format": "int64"
           },
-          "model": {
-            "type": "string",
-            "description": "ID of the model to use. Options: gpt-4o-transcribe, gpt-4o-mini-transcribe,\nwhisper-1, gpt-4o-transcribe-diarize."
+          "output_tokens": {
+            "type": "integer",
+            "format": "int64"
           },
-          "prompt": {
+          "project_id": {
             "type": [
               "string",
               "null"
-            ],
-            "description": "Optional text to guide the model's style or continue a previous audio segment.\nThe prompt should match the audio language."
-          },
-          "response_format": {
-            "oneOf": [
-              {
-                "type": "null"
-              },
-              {
-                "$ref": "#/components/schemas/AudioResponseFormat",
-                "description": "The format of the output."
-              }
             ]
           },
-          "stream": {
+          "project_name": {
             "type": [
-              "boolean",
+              "string",
               "null"
-            ],
-            "description": "If true, stream the response using server-sent events.\nNot supported for whisper-1."
+            ]
           },
-          "temperature": {
-            "type": [
-              "number",
-              "null"
-            ],
-            "format": "float",
-            "description": "The sampling temperature, between 0 and 1."
+          "request_count": {
+            "type": "integer",
+            "format": "int64"
           },
-          "timestamp_granularities": {
-            "type": [
-              "array",
-              "null"
-            ],
-            "items": {
-              "$ref": "#/components/schemas/TimestampGranularity"
-            },
-            "description": "The timestamp granularities to populate. Requires response_format=verbose_json."
+          "total_cost": {
+            "type": "number",
+            "format": "double"
+          },
+          "total_tokens": {
+            "type": "integer",
+            "format": "int64"
           }
         }
       },
-      "CreateTranslationRequest": {
+      "DailyProviderSpendResponse": {
         "type": "object",
-        "description": "Create translation request (POST /v1/audio/translations)\n\nNote: This endpoint accepts multipart/form-data. The `file` field\nis a file upload, not a JSON field.",
+        "description": "Daily usage breakdown by provider",
         "required": [
-          "model"
+          "date",
+          "provider",
+          "total_cost",
+          "input_tokens",
+          "output_tokens",
+          "total_tokens",
+          "request_count",
+          "image_count",
+          "audio_seconds",
+          "character_count"
         ],
         "properties": {
-          "model": {
+          "audio_seconds": {
+            "type": "integer",
+            "format": "int64",
+            "description": "**Hadrian Extension:** Audio duration in seconds"
+          },
+          "character_count": {
+            "type": "integer",
+            "format": "int64",
+            "description": "**Hadrian Extension:** Character count (TTS input)"
+          },
+          "date": {
             "type": "string",
-            "description": "ID of the model to use. Only whisper-1 is currently available."
+            "description": "Date (YYYY-MM-DD)"
           },
-          "prompt": {
-            "type": [
-              "string",
-              "null"
-            ],
-            "description": "Optional text to guide the model's style or continue a previous audio segment.\nThe prompt should be in English."
+          "image_count": {
+            "type": "integer",
+            "format": "int64",
+            "description": "**Hadrian Extension:** Number of images generated"
           },
-          "response_format": {
-            "oneOf": [
-              {
-                "type": "null"
-              },
-              {
-                "$ref": "#/components/schemas/AudioResponseFormat",
-                "description": "The format of the output."
-              }
-            ]
+          "input_tokens": {
+            "type": "integer",
+            "format": "int64",
+            "description": "Input tokens used"
           },
-          "temperature": {
-            "type": [
-              "number",
-              "null"
-            ],
-            "format": "float",
-            "description": "The sampling temperature, between 0 and 1."
+          "output_tokens": {
+            "type": "integer",
+            "format": "int64",
+            "description": "Output tokens used"
+          },
+          "provider": {
+            "type": "string",
+            "description": "Provider name"
+          },
+          "request_count": {
+            "type": "integer",
+            "format": "int64",
+            "description": "Number of requests"
+          },
+          "total_cost": {
+            "type": "number",
+            "format": "double",
+            "description": "Total cost in dollars for this day/provider"
+          },
+          "total_tokens": {
+            "type": "integer",
+            "format": "int64",
+            "description": "Total tokens used"
           }
         }
       },
-      "CreateUser": {
+      "DailySpendResponse": {
         "type": "object",
+        "description": "Daily usage breakdown",
         "required": [
-          "external_id"
+          "date",
+          "total_cost",
+          "input_tokens",
+          "output_tokens",
+          "total_tokens",
+          "request_count",
+          "image_count",
+          "audio_seconds",
+          "character_count"
         ],
         "properties": {
-          "email": {
-            "type": [
-              "string",
-              "null"
-            ]
+          "audio_seconds": {
+            "type": "integer",
+            "format": "int64",
+            "description": "**Hadrian Extension:** Audio duration in seconds"
           },
-          "external_id": {
+          "character_count": {
+            "type": "integer",
+            "format": "int64",
+            "description": "**Hadrian Extension:** Character count (TTS input)"
+          },
+          "date": {
             "type": "string",
-            "description": "External identifier (e.g., from SSO provider)"
+            "description": "Date (YYYY-MM-DD)"
           },
-          "name": {
-            "type": [
-              "string",
-              "null"
-            ]
+          "image_count": {
+            "type": "integer",
+            "format": "int64",
+            "description": "**Hadrian Extension:** Number of images generated"
+          },
+          "input_tokens": {
+            "type": "integer",
+            "format": "int64",
+            "description": "Input tokens used this day"
+          },
+          "output_tokens": {
+            "type": "integer",
+            "format": "int64",
+            "description": "Output tokens used this day"
+          },
+          "request_count": {
+            "type": "integer",
+            "format": "int64",
+            "description": "Number of requests this day"
+          },
+          "total_cost": {
+            "type": "number",
+            "format": "double",
+            "description": "Total cost in dollars for this day"
+          },
+          "total_tokens": {
+            "type": "integer",
+            "format": "int64",
+            "description": "Total tokens used this day"
           }
         }
       },
-      "CreateVectorStore": {
+      "DailyTeamSpendResponse": {
         "type": "object",
-        "description": "Request to create a new vector store.\n\n## Hadrian Extensions\n\nThe following fields are **Hadrian extensions** not present in the standard OpenAI API:\n- `owner`: Multi-tenancy support (required, specifies organization/project/user ownership)\n- `embedding_model`: Custom embedding model selection (default: text-embedding-3-small)\n- `embedding_dimensions`: Custom embedding dimensions (default: 1536)\n\n## OpenAI Compatibility Notes\n\n- `name` is optional (OpenAI-compatible), but a name will be auto-generated if not provided",
+        "description": "Daily usage breakdown by team",
         "required": [
-          "owner"
+          "date",
+          "total_cost",
+          "input_tokens",
+          "output_tokens",
+          "total_tokens",
+          "request_count",
+          "image_count",
+          "audio_seconds",
+          "character_count"
         ],
         "properties": {
-          "chunking_strategy": {
-            "oneOf": [
-              {
-                "type": "null"
-              },
-              {
-                "$ref": "#/components/schemas/ChunkingStrategy",
-                "description": "The chunking strategy used to chunk the file(s). If not set, will use the `auto` strategy.\nOnly applicable if `file_ids` is non-empty."
-              }
-            ]
+          "audio_seconds": {
+            "type": "integer",
+            "format": "int64"
           },
-          "description": {
-            "type": [
-              "string",
-              "null"
-            ],
-            "description": "Description of the vector store"
+          "character_count": {
+            "type": "integer",
+            "format": "int64"
           },
-          "embedding_dimensions": {
+          "date": {
+            "type": "string"
+          },
+          "image_count": {
             "type": "integer",
-            "format": "int32",
-            "description": "**Hadrian Extension:** Embedding dimensions (immutable after creation, default: 1536)"
+            "format": "int64"
           },
-          "embedding_model": {
-            "type": "string",
-            "description": "**Hadrian Extension:** Embedding model to use (immutable after creation, default: text-embedding-3-small)"
+          "input_tokens": {
+            "type": "integer",
+            "format": "int64"
           },
-          "expires_after": {
-            "oneOf": [
-              {
-                "type": "null"
-              },
-              {
-                "$ref": "#/components/schemas/ExpiresAfter",
-                "description": "Expiration policy"
-              }
-            ]
+          "output_tokens": {
+            "type": "integer",
+            "format": "int64"
           },
-          "file_ids": {
-            "type": "array",
-            "items": {
-              "type": "string",
-              "format": "uuid"
-            },
-            "description": "A list of File IDs that the vector store should use (max 500).\nFiles will be attached to the vector store after creation."
+          "request_count": {
+            "type": "integer",
+            "format": "int64"
           },
-          "metadata": {
+          "team_id": {
             "type": [
-              "object",
+              "string",
               "null"
-            ],
-            "description": "Custom metadata (up to 16 key-value pairs, keys max 64 chars, string values max 512 chars)",
-            "additionalProperties": {},
-            "propertyNames": {
-              "type": "string"
-            }
+            ]
           },
-          "name": {
+          "team_name": {
             "type": [
               "string",
               "null"
-            ],
-            "description": "Name of the vector store (optional, auto-generated if not provided)"
-          },
-          "owner": {
-            "$ref": "#/components/schemas/VectorStoreOwner",
-            "description": "**Hadrian Extension:** Owner of the vector store (required for multi-tenancy)"
-          }
-        }
-      },
-      "CreateVectorStoreFileRequest": {
-        "type": "object",
-        "description": "Request to add a file to a vector store",
-        "required": [
-          "file_id"
-        ],
-        "properties": {
-          "chunking_strategy": {
-            "oneOf": [
-              {
-                "type": "null"
-              },
-              {
-                "$ref": "#/components/schemas/ChunkingStrategy",
-                "description": "Chunking strategy for processing the file"
-              }
             ]
           },
-          "file_id": {
-            "type": "string",
-            "description": "The ID of the file to add (from the Files API)",
-            "example": "file-550e8400-e29b-41d4-a716-446655440000"
-          }
-        }
-      },
-      "CreatedApiKey": {
-        "allOf": [
-          {
-            "$ref": "#/components/schemas/ApiKey"
-          },
-          {
-            "type": "object",
-            "required": [
-              "key"
-            ],
-            "properties": {
-              "key": {
-                "type": "string",
-                "description": "The raw API key (only shown once at creation)"
-              }
-            }
-          }
-        ],
-        "description": "Returned on creation only (contains the raw key)"
-      },
-      "CreatedOrgScimConfig": {
-        "type": "object",
-        "description": "Result of creating a new SCIM config (includes the raw token, shown only once)",
-        "required": [
-          "config",
-          "token"
-        ],
-        "properties": {
-          "config": {
-            "$ref": "#/components/schemas/OrgScimConfig",
-            "description": "The created SCIM configuration"
+          "total_cost": {
+            "type": "number",
+            "format": "double"
           },
-          "token": {
-            "type": "string",
-            "description": "The raw SCIM bearer token (only shown once at creation time!)\nFormat: \"scim_<random_base64>\" (e.g., \"scim_Abc123XyzDef456...\")"
+          "total_tokens": {
+            "type": "integer",
+            "format": "int64"
           }
         }
       },
-      "DailySpendResponse": {
+      "DailyUserSpendResponse": {
         "type": "object",
-        "description": "Daily usage breakdown",
+        "description": "Daily usage breakdown by user",
         "required": [
           "date",
           "total_cost",
+          "input_tokens",
+          "output_tokens",
           "total_tokens",
-          "request_count"
+          "request_count",
+          "image_count",
+          "audio_seconds",
+          "character_count"
         ],
         "properties": {
+          "audio_seconds": {
+            "type": "integer",
+            "format": "int64"
+          },
+          "character_count": {
+            "type": "integer",
+            "format": "int64"
+          },
           "date": {
-            "type": "string",
-            "description": "Date (YYYY-MM-DD)"
+            "type": "string"
+          },
+          "image_count": {
+            "type": "integer",
+            "format": "int64"
+          },
+          "input_tokens": {
+            "type": "integer",
+            "format": "int64"
+          },
+          "output_tokens": {
+            "type": "integer",
+            "format": "int64"
           },
           "request_count": {
             "type": "integer",
-            "format": "int64",
-            "description": "Number of requests this day"
+            "format": "int64"
           },
           "total_cost": {
             "type": "number",
-            "format": "double",
-            "description": "Total cost in dollars for this day"
+            "format": "double"
           },
           "total_tokens": {
             "type": "integer",
-            "format": "int64",
-            "description": "Total tokens used this day"
+            "format": "int64"
+          },
+          "user_email": {
+            "type": [
+              "string",
+              "null"
+            ]
+          },
+          "user_id": {
+            "type": [
+              "string",
+              "null"
+            ]
+          },
+          "user_name": {
+            "type": [
+              "string",
+              "null"
+            ]
           }
         }
       },
@@ -16773,7 +23053,7 @@
               "string",
               "null"
             ],
-            "description": "Human-readable device description (parsed from user agent)\ne.g., \"Chrome 120 on Windows\""
+            "description": "Human-readable device description (parsed from user agent, truncated to 512 chars)\ne.g., \"Chrome 120 on Windows\""
           },
           "device_id": {
             "type": [
@@ -16794,7 +23074,7 @@
               "string",
               "null"
             ],
-            "description": "Raw User-Agent header value"
+            "description": "Raw User-Agent header value (truncated to 512 chars)"
           }
         }
       },
@@ -17130,11 +23410,14 @@
               "string",
               "null"
             ],
-            "description": "Reference to API key in secrets manager"
+            "description": "Reference to API key in secrets manager (or literal key if no SM configured)"
           },
           "base_url": {
             "type": "string"
           },
+          "config": {
+            "description": "Provider-specific configuration (e.g., region, credentials for Bedrock/Vertex)"
+          },
           "created_at": {
             "type": "string",
             "format": "date-time"
@@ -17161,7 +23444,18 @@
           },
           "provider_type": {
             "type": "string",
-            "description": "Provider type (e.g., \"open_ai\", \"anthropic\")"
+            "description": "Provider type (e.g., \"open_ai\", \"anthropic\", \"bedrock\", \"vertex\")"
+          },
+          "sovereignty": {
+            "oneOf": [
+              {
+                "type": "null"
+              },
+              {
+                "$ref": "#/components/schemas/SovereigntyMetadata",
+                "description": "Sovereignty and compliance metadata"
+              }
+            ]
           },
           "updated_at": {
             "type": "string",
@@ -17180,7 +23474,7 @@
           "data": {
             "type": "array",
             "items": {
-              "$ref": "#/components/schemas/DynamicProvider"
+              "$ref": "#/components/schemas/DynamicProviderResponse"
             },
             "description": "List of dynamic providers"
           },
@@ -17190,6 +23484,75 @@
           }
         }
       },
+      "DynamicProviderResponse": {
+        "type": "object",
+        "description": "Response DTO for dynamic providers",
+        "required": [
+          "id",
+          "name",
+          "owner",
+          "provider_type",
+          "base_url",
+          "has_api_key",
+          "models",
+          "is_enabled",
+          "created_at",
+          "updated_at"
+        ],
+        "properties": {
+          "base_url": {
+            "type": "string"
+          },
+          "config": {
+            "description": "Provider-specific configuration"
+          },
+          "created_at": {
+            "type": "string",
+            "format": "date-time"
+          },
+          "has_api_key": {
+            "type": "boolean",
+            "description": "Whether this provider has an API key configured"
+          },
+          "id": {
+            "type": "string",
+            "format": "uuid"
+          },
+          "is_enabled": {
+            "type": "boolean"
+          },
+          "models": {
+            "type": "array",
+            "items": {
+              "type": "string"
+            }
+          },
+          "name": {
+            "type": "string"
+          },
+          "owner": {
+            "$ref": "#/components/schemas/ProviderOwner"
+          },
+          "provider_type": {
+            "type": "string"
+          },
+          "sovereignty": {
+            "oneOf": [
+              {
+                "type": "null"
+              },
+              {
+                "$ref": "#/components/schemas/SovereigntyMetadata",
+                "description": "Sovereignty and compliance metadata"
+              }
+            ]
+          },
+          "updated_at": {
+            "type": "string",
+            "format": "date-time"
+          }
+        }
+      },
       "EmbeddingInput": {
         "oneOf": [
           {
@@ -18474,7 +24837,6 @@
       },
       "ListFilesQuery": {
         "type": "object",
-        "description": "Query parameters for listing files (OpenAI-compatible).",
         "required": [
           "owner_type",
           "owner_id"
@@ -18741,14 +25103,44 @@
         "required": [
           "model",
           "total_cost",
+          "input_tokens",
+          "output_tokens",
           "total_tokens",
-          "request_count"
+          "request_count",
+          "image_count",
+          "audio_seconds",
+          "character_count"
         ],
         "properties": {
+          "audio_seconds": {
+            "type": "integer",
+            "format": "int64",
+            "description": "**Hadrian Extension:** Audio duration in seconds"
+          },
+          "character_count": {
+            "type": "integer",
+            "format": "int64",
+            "description": "**Hadrian Extension:** Character count (TTS input)"
+          },
+          "image_count": {
+            "type": "integer",
+            "format": "int64",
+            "description": "**Hadrian Extension:** Number of images generated"
+          },
+          "input_tokens": {
+            "type": "integer",
+            "format": "int64",
+            "description": "Input tokens used by this model"
+          },
           "model": {
             "type": "string",
             "description": "Model name"
           },
+          "output_tokens": {
+            "type": "integer",
+            "format": "int64",
+            "description": "Output tokens used by this model"
+          },
           "request_count": {
             "type": "integer",
             "format": "int64",
@@ -19535,6 +25927,66 @@
           }
         }
       },
+      "OrgSpendResponse": {
+        "type": "object",
+        "description": "Usage breakdown by organization",
+        "required": [
+          "total_cost",
+          "input_tokens",
+          "output_tokens",
+          "total_tokens",
+          "request_count",
+          "image_count",
+          "audio_seconds",
+          "character_count"
+        ],
+        "properties": {
+          "audio_seconds": {
+            "type": "integer",
+            "format": "int64"
+          },
+          "character_count": {
+            "type": "integer",
+            "format": "int64"
+          },
+          "image_count": {
+            "type": "integer",
+            "format": "int64"
+          },
+          "input_tokens": {
+            "type": "integer",
+            "format": "int64"
+          },
+          "org_id": {
+            "type": [
+              "string",
+              "null"
+            ]
+          },
+          "org_name": {
+            "type": [
+              "string",
+              "null"
+            ]
+          },
+          "output_tokens": {
+            "type": "integer",
+            "format": "int64"
+          },
+          "request_count": {
+            "type": "integer",
+            "format": "int64"
+          },
+          "total_cost": {
+            "type": "number",
+            "format": "double"
+          },
+          "total_tokens": {
+            "type": "integer",
+            "format": "int64"
+          }
+        }
+      },
       "OrgSsoConfig": {
         "type": "object",
         "description": "Organization SSO Configuration.\n\nStores per-organization OIDC or SAML configuration for multi-tenant SSO.\nEach organization can have its own IdP, enabling IT admins to configure\ntheir own identity provider via the Admin UI.",
@@ -19873,60 +26325,6 @@
           }
         }
       },
-      "ParseSamlMetadataRequest": {
-        "type": "object",
-        "description": "Request to parse SAML IdP metadata from a URL.",
-        "required": [
-          "metadata_url"
-        ],
-        "properties": {
-          "metadata_url": {
-            "type": "string",
-            "description": "URL to fetch IdP metadata from (must be HTTPS for security)"
-          }
-        }
-      },
-      "ParsedSamlIdpConfig": {
-        "type": "object",
-        "description": "Parsed SAML IdP configuration extracted from metadata.\n\nThis is returned for admin review before saving - use the individual fields\nto populate the SSO config.",
-        "required": [
-          "entity_id",
-          "sso_url",
-          "certificates",
-          "name_id_formats"
-        ],
-        "properties": {
-          "certificates": {
-            "type": "array",
-            "items": {
-              "type": "string"
-            },
-            "description": "X.509 certificates for signature verification (PEM format)\nMultiple certificates may be present for key rollover"
-          },
-          "entity_id": {
-            "type": "string",
-            "description": "IdP entity identifier"
-          },
-          "name_id_formats": {
-            "type": "array",
-            "items": {
-              "type": "string"
-            },
-            "description": "Supported NameID formats"
-          },
-          "slo_url": {
-            "type": [
-              "string",
-              "null"
-            ],
-            "description": "IdP Single Logout service URL (if available)"
-          },
-          "sso_url": {
-            "type": "string",
-            "description": "IdP Single Sign-On service URL"
-          }
-        }
-      },
       "PartialImages": {
         "type": "object",
         "description": "Partial images configuration for streaming",
@@ -20128,6 +26526,67 @@
           "default"
         ]
       },
+      "PricingSourceSpendResponse": {
+        "type": "object",
+        "description": "Usage breakdown by pricing source",
+        "required": [
+          "pricing_source",
+          "total_cost",
+          "input_tokens",
+          "output_tokens",
+          "total_tokens",
+          "request_count",
+          "image_count",
+          "audio_seconds",
+          "character_count"
+        ],
+        "properties": {
+          "audio_seconds": {
+            "type": "integer",
+            "format": "int64",
+            "description": "**Hadrian Extension:** Audio duration in seconds"
+          },
+          "character_count": {
+            "type": "integer",
+            "format": "int64",
+            "description": "**Hadrian Extension:** Character count (TTS input)"
+          },
+          "image_count": {
+            "type": "integer",
+            "format": "int64",
+            "description": "**Hadrian Extension:** Number of images generated"
+          },
+          "input_tokens": {
+            "type": "integer",
+            "format": "int64",
+            "description": "Input tokens"
+          },
+          "output_tokens": {
+            "type": "integer",
+            "format": "int64",
+            "description": "Output tokens"
+          },
+          "pricing_source": {
+            "type": "string",
+            "description": "Pricing source (provider, provider_config, pricing_config, catalog, none)"
+          },
+          "request_count": {
+            "type": "integer",
+            "format": "int64",
+            "description": "Number of requests"
+          },
+          "total_cost": {
+            "type": "number",
+            "format": "double",
+            "description": "Total cost in dollars for this pricing source"
+          },
+          "total_tokens": {
+            "type": "integer",
+            "format": "int64",
+            "description": "Total tokens"
+          }
+        }
+      },
       "Project": {
         "type": "object",
         "required": [
@@ -20278,177 +26737,65 @@
           }
         }
       },
-      "Prompt": {
+      "ProjectSpendResponse": {
         "type": "object",
-        "description": "A reusable system prompt template",
+        "description": "Usage breakdown by project",
         "required": [
-          "id",
-          "owner_type",
-          "owner_id",
-          "name",
-          "content",
-          "created_at",
-          "updated_at"
+          "total_cost",
+          "input_tokens",
+          "output_tokens",
+          "total_tokens",
+          "request_count",
+          "image_count",
+          "audio_seconds",
+          "character_count"
         ],
         "properties": {
-          "content": {
-            "type": "string",
-            "description": "The actual prompt content (system message template)"
-          },
-          "created_at": {
-            "type": "string",
-            "format": "date-time"
-          },
-          "description": {
-            "type": [
-              "string",
-              "null"
-            ],
-            "description": "Optional description of what this prompt does"
-          },
-          "id": {
-            "type": "string",
-            "format": "uuid"
-          },
-          "metadata": {
-            "type": [
-              "object",
-              "null"
-            ],
-            "description": "Optional metadata (e.g., recommended temperature, max_tokens, tags)",
-            "additionalProperties": {},
-            "propertyNames": {
-              "type": "string"
-            }
+          "audio_seconds": {
+            "type": "integer",
+            "format": "int64"
           },
-          "name": {
-            "type": "string",
-            "description": "Name of the prompt template"
+          "character_count": {
+            "type": "integer",
+            "format": "int64"
           },
-          "owner_id": {
-            "type": "string",
-            "format": "uuid"
+          "image_count": {
+            "type": "integer",
+            "format": "int64"
           },
-          "owner_type": {
-            "$ref": "#/components/schemas/PromptOwnerType"
+          "input_tokens": {
+            "type": "integer",
+            "format": "int64"
           },
-          "updated_at": {
-            "type": "string",
-            "format": "date-time"
-          }
-        }
-      },
-      "PromptListResponse": {
-        "type": "object",
-        "description": "Paginated list of prompts",
-        "required": [
-          "data",
-          "pagination"
-        ],
-        "properties": {
-          "data": {
-            "type": "array",
-            "items": {
-              "$ref": "#/components/schemas/Prompt"
-            },
-            "description": "List of prompts"
+          "output_tokens": {
+            "type": "integer",
+            "format": "int64"
           },
-          "pagination": {
-            "$ref": "#/components/schemas/PaginationMeta",
-            "description": "Pagination metadata"
-          }
-        }
-      },
-      "PromptOwner": {
-        "oneOf": [
-          {
-            "type": "object",
-            "required": [
-              "organization_id",
-              "type"
-            ],
-            "properties": {
-              "organization_id": {
-                "type": "string",
-                "format": "uuid"
-              },
-              "type": {
-                "type": "string",
-                "enum": [
-                  "organization"
-                ]
-              }
-            }
+          "project_id": {
+            "type": [
+              "string",
+              "null"
+            ]
           },
-          {
-            "type": "object",
-            "required": [
-              "team_id",
-              "type"
-            ],
-            "properties": {
-              "team_id": {
-                "type": "string",
-                "format": "uuid"
-              },
-              "type": {
-                "type": "string",
-                "enum": [
-                  "team"
-                ]
-              }
-            }
+          "project_name": {
+            "type": [
+              "string",
+              "null"
+            ]
           },
-          {
-            "type": "object",
-            "required": [
-              "project_id",
-              "type"
-            ],
-            "properties": {
-              "project_id": {
-                "type": "string",
-                "format": "uuid"
-              },
-              "type": {
-                "type": "string",
-                "enum": [
-                  "project"
-                ]
-              }
-            }
+          "request_count": {
+            "type": "integer",
+            "format": "int64"
           },
-          {
-            "type": "object",
-            "required": [
-              "user_id",
-              "type"
-            ],
-            "properties": {
-              "type": {
-                "type": "string",
-                "enum": [
-                  "user"
-                ]
-              },
-              "user_id": {
-                "type": "string",
-                "format": "uuid"
-              }
-            }
+          "total_cost": {
+            "type": "number",
+            "format": "double"
+          },
+          "total_tokens": {
+            "type": "integer",
+            "format": "int64"
           }
-        ],
-        "description": "Owner specification for creating a prompt"
-      },
-      "PromptOwnerType": {
-        "type": "string",
-        "description": "Owner type for prompts (organization, team, project, or user)",
-        "enum": [
-          "organization",
-          "team",
-          "project",
-          "user"
-        ]
+        }
       },
       "ProviderCircuitBreakerResponse": {
         "type": "object",
@@ -20639,10 +26986,40 @@
         "required": [
           "provider",
           "total_cost",
+          "input_tokens",
+          "output_tokens",
           "total_tokens",
-          "request_count"
+          "request_count",
+          "image_count",
+          "audio_seconds",
+          "character_count"
         ],
         "properties": {
+          "audio_seconds": {
+            "type": "integer",
+            "format": "int64",
+            "description": "**Hadrian Extension:** Audio duration in seconds"
+          },
+          "character_count": {
+            "type": "integer",
+            "format": "int64",
+            "description": "**Hadrian Extension:** Character count (TTS input)"
+          },
+          "image_count": {
+            "type": "integer",
+            "format": "int64",
+            "description": "**Hadrian Extension:** Number of images generated"
+          },
+          "input_tokens": {
+            "type": "integer",
+            "format": "int64",
+            "description": "Input tokens used by this provider"
+          },
+          "output_tokens": {
+            "type": "integer",
+            "format": "int64",
+            "description": "Output tokens used by this provider"
+          },
           "provider": {
             "type": "string",
             "description": "Provider name"
@@ -20881,10 +27258,25 @@
         "description": "Usage breakdown by HTTP referer",
         "required": [
           "total_cost",
+          "input_tokens",
+          "output_tokens",
           "total_tokens",
-          "request_count"
+          "request_count",
+          "image_count",
+          "audio_seconds",
+          "character_count"
         ],
         "properties": {
+          "audio_seconds": {
+            "type": "integer",
+            "format": "int64",
+            "description": "**Hadrian Extension:** Audio duration in seconds"
+          },
+          "character_count": {
+            "type": "integer",
+            "format": "int64",
+            "description": "**Hadrian Extension:** Character count (TTS input)"
+          },
           "http_referer": {
             "type": [
               "string",
@@ -20892,6 +27284,21 @@
             ],
             "description": "HTTP referer header value"
           },
+          "image_count": {
+            "type": "integer",
+            "format": "int64",
+            "description": "**Hadrian Extension:** Number of images generated"
+          },
+          "input_tokens": {
+            "type": "integer",
+            "format": "int64",
+            "description": "Input tokens used from this referer"
+          },
+          "output_tokens": {
+            "type": "integer",
+            "format": "int64",
+            "description": "Output tokens used from this referer"
+          },
           "request_count": {
             "type": "integer",
             "format": "int64",
@@ -21086,6 +27493,25 @@
           }
         }
       },
+      "SelfServiceProviderListResponse": {
+        "type": "object",
+        "description": "Paginated list of dynamic providers",
+        "required": [
+          "data",
+          "pagination"
+        ],
+        "properties": {
+          "data": {
+            "type": "array",
+            "items": {
+              "$ref": "#/components/schemas/DynamicProviderResponse"
+            }
+          },
+          "pagination": {
+            "$ref": "#/components/schemas/PaginationMeta"
+          }
+        }
+      },
       "ServiceAccount": {
         "type": "object",
         "description": "A service account is a first-class machine identity that can own API keys\nand carry roles for RBAC evaluation. This enables unified authorization\nacross human users and machine identities.",
@@ -21218,6 +27644,7 @@
           "teams",
           "projects",
           "auth_method",
+          "runtime_mode",
           "server_time"
         ],
         "properties": {
@@ -21243,6 +27670,10 @@
             },
             "description": "Project access (direct memberships)"
           },
+          "runtime_mode": {
+            "type": "string",
+            "description": "Runtime mode: \"server\" for native, \"wasm\" for browser"
+          },
           "server_time": {
             "type": "string",
             "format": "date-time",
@@ -21287,6 +27718,14 @@
           "enhanced_enabled"
         ],
         "properties": {
+          "current_session_id": {
+            "type": [
+              "string",
+              "null"
+            ],
+            "format": "uuid",
+            "description": "The session ID of the current request (if authenticated via session cookie).\nAllows the UI to highlight the current session and warn before self-revocation."
+          },
           "data": {
             "type": "array",
             "items": {
@@ -21620,53 +28059,185 @@
             "items": {
               "type": "string"
             },
-            "description": "Organization IDs the user belongs to"
+            "description": "Organization IDs the user belongs to"
+          },
+          "project_ids": {
+            "type": "array",
+            "items": {
+              "type": "string"
+            },
+            "description": "Project IDs the user belongs to"
+          },
+          "roles": {
+            "type": "array",
+            "items": {
+              "type": "string"
+            },
+            "description": "User's roles"
+          },
+          "service_account_id": {
+            "type": [
+              "string",
+              "null"
+            ],
+            "description": "Service account ID (if simulating service account auth)"
+          },
+          "team_ids": {
+            "type": "array",
+            "items": {
+              "type": "string"
+            },
+            "description": "Team IDs the user belongs to"
+          },
+          "user_id": {
+            "type": [
+              "string",
+              "null"
+            ],
+            "description": "User ID (internal)"
+          }
+        }
+      },
+      "SortOrder": {
+        "type": "string",
+        "description": "Sort order for list queries.\n\nOpenAI-compatible sort order parameter for paginated list endpoints.",
+        "enum": [
+          "asc",
+          "desc"
+        ]
+      },
+      "SovereigntyMetadata": {
+        "type": "object",
+        "description": "Sovereignty and compliance metadata for providers and models.\n\nWhen set at the provider level, these values apply to all models\nfrom that provider. Per-model overrides take precedence.",
+        "properties": {
+          "certifications": {
+            "type": "array",
+            "items": {
+              "type": "string"
+            },
+            "description": "Compliance certifications and regulatory frameworks.\nWell-known values: \"gdpr\", \"hipaa\", \"soc2\", \"soc2-type2\", \"iso27001\",\n\"fedramp\", \"fedramp-high\", \"pci-dss\", \"c5\", \"ismap\", \"hipaa-baa\", \"ccpa\", \"dpa\""
+          },
+          "custom": {
+            "type": "object",
+            "description": "Custom key-value metadata. Keys should match a defined custom field.",
+            "additionalProperties": {
+              "type": "string"
+            },
+            "propertyNames": {
+              "type": "string"
+            }
+          },
+          "data_retention": {
+            "type": [
+              "string",
+              "null"
+            ],
+            "description": "Provider's data retention policy for request/response data.\nWell-known values: \"none\", \"30d\", \"90d\", \"1y\", \"indefinite\""
+          },
+          "hq_country": {
+            "type": [
+              "string",
+              "null"
+            ],
+            "description": "ISO 3166-1 alpha-2 country code of the provider's headquarters."
+          },
+          "inference_countries": {
+            "type": "array",
+            "items": {
+              "type": "string"
+            },
+            "description": "ISO 3166-1 alpha-2 country codes where model inference runs."
+          },
+          "license": {
+            "type": [
+              "string",
+              "null"
+            ],
+            "description": "Model license identifier.\nWell-known values: \"proprietary\", \"apache-2.0\", \"mit\", \"llama-3.1\",\n\"gemma\", \"mistral\", \"cc-by-4.0\", \"cc-by-nc-4.0\""
+          },
+          "notes": {
+            "type": [
+              "string",
+              "null"
+            ],
+            "description": "Free-form notes for additional context."
+          },
+          "on_prem": {
+            "type": [
+              "boolean",
+              "null"
+            ],
+            "description": "Whether this provider/model runs on infrastructure operated by the org."
+          },
+          "trains_on_data": {
+            "type": [
+              "boolean",
+              "null"
+            ],
+            "description": "Whether the provider trains on customer data.\nNone = unknown, true = yes, false = no (or opt-out available)."
+          }
+        }
+      },
+      "SovereigntyRequirements": {
+        "type": "object",
+        "description": "Sovereignty requirements for API key restrictions.\n\nWhen set on an API key, only models whose resolved sovereignty metadata\nsatisfies all specified requirements can be used.",
+        "properties": {
+          "allowed_inference_countries": {
+            "type": [
+              "array",
+              "null"
+            ],
+            "items": {
+              "type": "string"
+            },
+            "description": "Only allow models with inference in these countries."
           },
-          "project_ids": {
-            "type": "array",
+          "allowed_licenses": {
+            "type": [
+              "array",
+              "null"
+            ],
             "items": {
               "type": "string"
             },
-            "description": "Project IDs the user belongs to"
+            "description": "Only allow models with these licenses."
           },
-          "roles": {
-            "type": "array",
+          "blocked_hq_countries": {
+            "type": [
+              "array",
+              "null"
+            ],
             "items": {
               "type": "string"
             },
-            "description": "User's roles"
+            "description": "Exclude models from providers headquartered in these countries."
           },
-          "service_account_id": {
+          "require_on_prem": {
             "type": [
-              "string",
+              "boolean",
               "null"
             ],
-            "description": "Service account ID (if simulating service account auth)"
+            "description": "Only allow on-prem providers (sovereignty.on_prem == true)."
           },
-          "team_ids": {
-            "type": "array",
-            "items": {
-              "type": "string"
-            },
-            "description": "Team IDs the user belongs to"
+          "require_open_weights": {
+            "type": [
+              "boolean",
+              "null"
+            ],
+            "description": "Only allow open-weight models (open_weights == true)."
           },
-          "user_id": {
+          "required_certifications": {
             "type": [
-              "string",
+              "array",
               "null"
             ],
-            "description": "User ID (internal)"
+            "items": {
+              "type": "string"
+            },
+            "description": "Provider must have ALL of these certifications."
           }
         }
       },
-      "SortOrder": {
-        "type": "string",
-        "description": "Sort order for list queries.\n\nOpenAI-compatible sort order parameter for paginated list endpoints.",
-        "enum": [
-          "asc",
-          "desc"
-        ]
-      },
       "SpeechResponseFormat": {
         "type": "string",
         "description": "Audio output format for text-to-speech.",
@@ -22493,6 +29064,238 @@
           }
         }
       },
+      "TeamSpendResponse": {
+        "type": "object",
+        "description": "Usage breakdown by team",
+        "required": [
+          "total_cost",
+          "input_tokens",
+          "output_tokens",
+          "total_tokens",
+          "request_count",
+          "image_count",
+          "audio_seconds",
+          "character_count"
+        ],
+        "properties": {
+          "audio_seconds": {
+            "type": "integer",
+            "format": "int64"
+          },
+          "character_count": {
+            "type": "integer",
+            "format": "int64"
+          },
+          "image_count": {
+            "type": "integer",
+            "format": "int64"
+          },
+          "input_tokens": {
+            "type": "integer",
+            "format": "int64"
+          },
+          "output_tokens": {
+            "type": "integer",
+            "format": "int64"
+          },
+          "request_count": {
+            "type": "integer",
+            "format": "int64"
+          },
+          "team_id": {
+            "type": [
+              "string",
+              "null"
+            ]
+          },
+          "team_name": {
+            "type": [
+              "string",
+              "null"
+            ]
+          },
+          "total_cost": {
+            "type": "number",
+            "format": "double"
+          },
+          "total_tokens": {
+            "type": "integer",
+            "format": "int64"
+          }
+        }
+      },
+      "Template": {
+        "type": "object",
+        "description": "A reusable system template",
+        "required": [
+          "id",
+          "owner_type",
+          "owner_id",
+          "name",
+          "content",
+          "created_at",
+          "updated_at"
+        ],
+        "properties": {
+          "content": {
+            "type": "string",
+            "description": "The actual template content (system message template)"
+          },
+          "created_at": {
+            "type": "string",
+            "format": "date-time"
+          },
+          "description": {
+            "type": [
+              "string",
+              "null"
+            ],
+            "description": "Optional description of what this template does"
+          },
+          "id": {
+            "type": "string",
+            "format": "uuid"
+          },
+          "metadata": {
+            "type": [
+              "object",
+              "null"
+            ],
+            "description": "Optional metadata (e.g., recommended temperature, max_tokens, tags)",
+            "additionalProperties": {},
+            "propertyNames": {
+              "type": "string"
+            }
+          },
+          "name": {
+            "type": "string",
+            "description": "Name of the template"
+          },
+          "owner_id": {
+            "type": "string",
+            "format": "uuid"
+          },
+          "owner_type": {
+            "$ref": "#/components/schemas/TemplateOwnerType"
+          },
+          "updated_at": {
+            "type": "string",
+            "format": "date-time"
+          }
+        }
+      },
+      "TemplateListResponse": {
+        "type": "object",
+        "description": "Paginated list of templates",
+        "required": [
+          "data",
+          "pagination"
+        ],
+        "properties": {
+          "data": {
+            "type": "array",
+            "items": {
+              "$ref": "#/components/schemas/Template"
+            },
+            "description": "List of templates"
+          },
+          "pagination": {
+            "$ref": "#/components/schemas/PaginationMeta",
+            "description": "Pagination metadata"
+          }
+        }
+      },
+      "TemplateOwner": {
+        "oneOf": [
+          {
+            "type": "object",
+            "required": [
+              "organization_id",
+              "type"
+            ],
+            "properties": {
+              "organization_id": {
+                "type": "string",
+                "format": "uuid"
+              },
+              "type": {
+                "type": "string",
+                "enum": [
+                  "organization"
+                ]
+              }
+            }
+          },
+          {
+            "type": "object",
+            "required": [
+              "team_id",
+              "type"
+            ],
+            "properties": {
+              "team_id": {
+                "type": "string",
+                "format": "uuid"
+              },
+              "type": {
+                "type": "string",
+                "enum": [
+                  "team"
+                ]
+              }
+            }
+          },
+          {
+            "type": "object",
+            "required": [
+              "project_id",
+              "type"
+            ],
+            "properties": {
+              "project_id": {
+                "type": "string",
+                "format": "uuid"
+              },
+              "type": {
+                "type": "string",
+                "enum": [
+                  "project"
+                ]
+              }
+            }
+          },
+          {
+            "type": "object",
+            "required": [
+              "user_id",
+              "type"
+            ],
+            "properties": {
+              "type": {
+                "type": "string",
+                "enum": [
+                  "user"
+                ]
+              },
+              "user_id": {
+                "type": "string",
+                "format": "uuid"
+              }
+            }
+          }
+        ],
+        "description": "Owner specification for creating a template"
+      },
+      "TemplateOwnerType": {
+        "type": "string",
+        "description": "Owner type for templates (organization, team, project, or user)",
+        "enum": [
+          "organization",
+          "team",
+          "project",
+          "user"
+        ]
+      },
       "TestMappingRequest": {
         "type": "object",
         "description": "Request to test SSO group mapping resolution",
@@ -23353,12 +30156,12 @@
       "UpdateDynamicProvider": {
         "type": "object",
         "properties": {
-          "api_key_secret_ref": {
+          "api_key": {
             "type": [
               "string",
               "null"
             ],
-            "description": "Reference to API key in secrets manager"
+            "description": "Raw API key (stored in secrets manager if available, otherwise stored directly)"
           },
           "base_url": {
             "type": [
@@ -23366,6 +30169,9 @@
               "null"
             ]
           },
+          "config": {
+            "description": "Provider-specific configuration (e.g., region, credentials for Bedrock/Vertex)"
+          },
           "is_enabled": {
             "type": [
               "boolean",
@@ -23381,6 +30187,17 @@
               "type": "string"
             },
             "description": "List of supported model names"
+          },
+          "sovereignty": {
+            "oneOf": [
+              {
+                "type": "null"
+              },
+              {
+                "$ref": "#/components/schemas/SovereigntyMetadata",
+                "description": "Sovereignty and compliance metadata (set to null to clear)"
+              }
+            ]
           }
         }
       },
@@ -23914,9 +30731,100 @@
           }
         }
       },
-      "UpdatePrompt": {
+      "UpdateServiceAccount": {
+        "type": "object",
+        "description": "Request to update an existing service account",
+        "properties": {
+          "description": {
+            "type": [
+              "string",
+              "null"
+            ],
+            "description": "New description"
+          },
+          "name": {
+            "type": [
+              "string",
+              "null"
+            ],
+            "description": "New display name"
+          },
+          "roles": {
+            "type": [
+              "array",
+              "null"
+            ],
+            "items": {
+              "type": "string"
+            },
+            "description": "New roles (replaces existing roles)"
+          }
+        }
+      },
+      "UpdateSsoGroupMapping": {
+        "type": "object",
+        "description": "Request to update an existing SSO group mapping.\n\nAll fields are optional - only provided fields will be updated.",
+        "properties": {
+          "idp_group": {
+            "type": [
+              "string",
+              "null"
+            ],
+            "description": "Update the IdP group name"
+          },
+          "priority": {
+            "type": [
+              "integer",
+              "null"
+            ],
+            "format": "int32",
+            "description": "Update the priority (higher = wins when multiple mappings target same team)"
+          },
+          "role": {
+            "type": [
+              "string",
+              "null"
+            ],
+            "description": "Update the role (set to null to remove role assignment)"
+          },
+          "team_id": {
+            "type": [
+              "string",
+              "null"
+            ],
+            "format": "uuid",
+            "description": "Update the team assignment (set to null to remove team assignment)"
+          }
+        }
+      },
+      "UpdateTeam": {
+        "type": "object",
+        "properties": {
+          "name": {
+            "type": [
+              "string",
+              "null"
+            ],
+            "description": "New display name"
+          }
+        }
+      },
+      "UpdateTeamMember": {
+        "type": "object",
+        "description": "Request to update a team member's role",
+        "required": [
+          "role"
+        ],
+        "properties": {
+          "role": {
+            "type": "string",
+            "description": "New role to assign"
+          }
+        }
+      },
+      "UpdateTemplate": {
         "type": "object",
-        "description": "Request to update a prompt",
+        "description": "Request to update a template",
         "properties": {
           "content": {
             "type": [
@@ -23952,153 +30860,251 @@
           }
         }
       },
-      "UpdateServiceAccount": {
+      "UpdateUser": {
         "type": "object",
-        "description": "Request to update an existing service account",
         "properties": {
-          "description": {
+          "email": {
             "type": [
               "string",
               "null"
-            ],
-            "description": "New description"
+            ]
           },
           "name": {
+            "type": [
+              "string",
+              "null"
+            ]
+          }
+        }
+      },
+      "UpdateVectorStore": {
+        "type": "object",
+        "description": "Request to update a vector store (vector store).\n\n## Hadrian Extensions\n\nThe following field is a **Hadrian extension** not present in the standard OpenAI API:\n- `description`: Human-readable description",
+        "properties": {
+          "description": {
             "type": [
               "string",
               "null"
             ],
-            "description": "New display name"
+            "description": "**Hadrian Extension:** New description"
           },
-          "roles": {
+          "expires_after": {
+            "oneOf": [
+              {
+                "type": "null"
+              },
+              {
+                "$ref": "#/components/schemas/ExpiresAfter",
+                "description": "New expiration policy"
+              }
+            ]
+          },
+          "metadata": {
             "type": [
-              "array",
+              "object",
               "null"
             ],
-            "items": {
+            "description": "New metadata (replaces existing, up to 16 key-value pairs, keys max 64 chars, string values max 512 chars)",
+            "additionalProperties": {},
+            "propertyNames": {
               "type": "string"
-            },
-            "description": "New roles (replaces existing roles)"
+            }
+          },
+          "name": {
+            "type": [
+              "string",
+              "null"
+            ],
+            "description": "New name"
           }
         }
       },
-      "UpdateSsoGroupMapping": {
+      "UsageLogExportFormat": {
+        "type": "string",
+        "description": "Export format for usage logs",
+        "enum": [
+          "csv",
+          "jsonl"
+        ]
+      },
+      "UsageLogListResponse": {
         "type": "object",
-        "description": "Request to update an existing SSO group mapping.\n\nAll fields are optional - only provided fields will be updated.",
+        "description": "Paginated list of usage log records",
+        "required": [
+          "data",
+          "pagination"
+        ],
         "properties": {
-          "idp_group": {
+          "data": {
+            "type": "array",
+            "items": {
+              "$ref": "#/components/schemas/UsageLogResponse"
+            }
+          },
+          "pagination": {
+            "$ref": "#/components/schemas/PaginationMeta"
+          }
+        }
+      },
+      "UsageLogResponse": {
+        "type": "object",
+        "description": "Individual usage log entry response",
+        "required": [
+          "id",
+          "recorded_at",
+          "request_id",
+          "model",
+          "provider",
+          "input_tokens",
+          "output_tokens",
+          "cached_tokens",
+          "reasoning_tokens",
+          "cost",
+          "streamed",
+          "cancelled",
+          "pricing_source"
+        ],
+        "properties": {
+          "api_key_id": {
             "type": [
               "string",
               "null"
             ],
-            "description": "Update the IdP group name"
+            "format": "uuid"
           },
-          "priority": {
+          "audio_seconds": {
             "type": [
               "integer",
               "null"
             ],
-            "format": "int32",
-            "description": "Update the priority (higher = wins when multiple mappings target same team)"
+            "format": "int32"
           },
-          "role": {
+          "cached_tokens": {
+            "type": "integer",
+            "format": "int32"
+          },
+          "cancelled": {
+            "type": "boolean"
+          },
+          "character_count": {
+            "type": [
+              "integer",
+              "null"
+            ],
+            "format": "int32"
+          },
+          "cost": {
+            "type": "number",
+            "format": "double",
+            "description": "Cost in dollars"
+          },
+          "finish_reason": {
             "type": [
               "string",
               "null"
+            ]
+          },
+          "http_referer": {
+            "type": [
+              "string",
+              "null"
+            ]
+          },
+          "id": {
+            "type": "string",
+            "format": "uuid"
+          },
+          "image_count": {
+            "type": [
+              "integer",
+              "null"
             ],
-            "description": "Update the role (set to null to remove role assignment)"
+            "format": "int32"
           },
-          "team_id": {
+          "input_tokens": {
+            "type": "integer",
+            "format": "int32"
+          },
+          "latency_ms": {
+            "type": [
+              "integer",
+              "null"
+            ],
+            "format": "int32"
+          },
+          "model": {
+            "type": "string"
+          },
+          "org_id": {
             "type": [
               "string",
               "null"
             ],
-            "format": "uuid",
-            "description": "Update the team assignment (set to null to remove team assignment)"
-          }
-        }
-      },
-      "UpdateTeam": {
-        "type": "object",
-        "properties": {
-          "name": {
+            "format": "uuid"
+          },
+          "output_tokens": {
+            "type": "integer",
+            "format": "int32"
+          },
+          "pricing_source": {
+            "type": "string"
+          },
+          "project_id": {
             "type": [
               "string",
               "null"
             ],
-            "description": "New display name"
-          }
-        }
-      },
-      "UpdateTeamMember": {
-        "type": "object",
-        "description": "Request to update a team member's role",
-        "required": [
-          "role"
-        ],
-        "properties": {
-          "role": {
-            "type": "string",
-            "description": "New role to assign"
-          }
-        }
-      },
-      "UpdateUser": {
-        "type": "object",
-        "properties": {
-          "email": {
+            "format": "uuid"
+          },
+          "provider": {
+            "type": "string"
+          },
+          "provider_source": {
             "type": [
               "string",
               "null"
             ]
           },
-          "name": {
+          "reasoning_tokens": {
+            "type": "integer",
+            "format": "int32"
+          },
+          "recorded_at": {
+            "type": "string"
+          },
+          "request_id": {
+            "type": "string"
+          },
+          "service_account_id": {
             "type": [
               "string",
               "null"
-            ]
-          }
-        }
-      },
-      "UpdateVectorStore": {
-        "type": "object",
-        "description": "Request to update a vector store (vector store).\n\n## Hadrian Extensions\n\nThe following field is a **Hadrian extension** not present in the standard OpenAI API:\n- `description`: Human-readable description",
-        "properties": {
-          "description": {
+            ],
+            "format": "uuid"
+          },
+          "status_code": {
             "type": [
-              "string",
+              "integer",
               "null"
             ],
-            "description": "**Hadrian Extension:** New description"
+            "format": "int32"
           },
-          "expires_after": {
-            "oneOf": [
-              {
-                "type": "null"
-              },
-              {
-                "$ref": "#/components/schemas/ExpiresAfter",
-                "description": "New expiration policy"
-              }
-            ]
+          "streamed": {
+            "type": "boolean"
           },
-          "metadata": {
+          "team_id": {
             "type": [
-              "object",
+              "string",
               "null"
             ],
-            "description": "New metadata (replaces existing, up to 16 key-value pairs, keys max 64 chars, string values max 512 chars)",
-            "additionalProperties": {},
-            "propertyNames": {
-              "type": "string"
-            }
+            "format": "uuid"
           },
-          "name": {
+          "user_id": {
             "type": [
               "string",
               "null"
             ],
-            "description": "New name"
+            "format": "uuid"
           }
         }
       },
@@ -24127,10 +31133,25 @@
         "description": "Usage summary response",
         "required": [
           "total_cost",
+          "input_tokens",
+          "output_tokens",
           "total_tokens",
-          "request_count"
+          "request_count",
+          "image_count",
+          "audio_seconds",
+          "character_count"
         ],
         "properties": {
+          "audio_seconds": {
+            "type": "integer",
+            "format": "int64",
+            "description": "**Hadrian Extension:** Audio duration in seconds"
+          },
+          "character_count": {
+            "type": "integer",
+            "format": "int64",
+            "description": "**Hadrian Extension:** Character count (TTS input)"
+          },
           "first_request_at": {
             "type": [
               "string",
@@ -24138,6 +31159,16 @@
             ],
             "description": "First request timestamp (RFC3339)"
           },
+          "image_count": {
+            "type": "integer",
+            "format": "int64",
+            "description": "**Hadrian Extension:** Number of images generated"
+          },
+          "input_tokens": {
+            "type": "integer",
+            "format": "int64",
+            "description": "Input tokens used"
+          },
           "last_request_at": {
             "type": [
               "string",
@@ -24145,6 +31176,11 @@
             ],
             "description": "Last request timestamp (RFC3339)"
           },
+          "output_tokens": {
+            "type": "integer",
+            "format": "int64",
+            "description": "Output tokens used"
+          },
           "request_count": {
             "type": "integer",
             "format": "int64",
@@ -24858,6 +31894,76 @@
           }
         }
       },
+      "UserSpendResponse": {
+        "type": "object",
+        "description": "Usage breakdown by user",
+        "required": [
+          "total_cost",
+          "input_tokens",
+          "output_tokens",
+          "total_tokens",
+          "request_count",
+          "image_count",
+          "audio_seconds",
+          "character_count"
+        ],
+        "properties": {
+          "audio_seconds": {
+            "type": "integer",
+            "format": "int64"
+          },
+          "character_count": {
+            "type": "integer",
+            "format": "int64"
+          },
+          "image_count": {
+            "type": "integer",
+            "format": "int64"
+          },
+          "input_tokens": {
+            "type": "integer",
+            "format": "int64"
+          },
+          "output_tokens": {
+            "type": "integer",
+            "format": "int64"
+          },
+          "request_count": {
+            "type": "integer",
+            "format": "int64"
+          },
+          "total_cost": {
+            "type": "number",
+            "format": "double",
+            "description": "Total cost in dollars"
+          },
+          "total_tokens": {
+            "type": "integer",
+            "format": "int64"
+          },
+          "user_email": {
+            "type": [
+              "string",
+              "null"
+            ],
+            "description": "User email"
+          },
+          "user_id": {
+            "type": [
+              "string",
+              "null"
+            ],
+            "description": "User ID (null for unattributed usage)"
+          },
+          "user_name": {
+            "type": [
+              "string",
+              "null"
+            ],
+            "description": "User display name"
+          }
+        }
+      },
       "ValidateCelRequest": {
         "type": "object",
         "description": "Request to validate a CEL expression",
@@ -25396,6 +32502,108 @@
           "marin",
           "cedar"
         ]
+      },
+      "WebFetchRequest": {
+        "type": "object",
+        "required": [
+          "url"
+        ],
+        "properties": {
+          "max_length": {
+            "type": [
+              "integer",
+              "null"
+            ],
+            "minimum": 0
+          },
+          "url": {
+            "type": "string"
+          }
+        }
+      },
+      "WebFetchResponse": {
+        "type": "object",
+        "required": [
+          "url",
+          "content",
+          "content_length"
+        ],
+        "properties": {
+          "content": {
+            "type": "string"
+          },
+          "content_length": {
+            "type": "integer",
+            "minimum": 0
+          },
+          "content_type": {
+            "type": [
+              "string",
+              "null"
+            ]
+          },
+          "url": {
+            "type": "string"
+          }
+        }
+      },
+      "WebSearchRequest": {
+        "type": "object",
+        "required": [
+          "query"
+        ],
+        "properties": {
+          "max_results": {
+            "type": [
+              "integer",
+              "null"
+            ],
+            "minimum": 0
+          },
+          "query": {
+            "type": "string"
+          }
+        }
+      },
+      "WebSearchResponse": {
+        "type": "object",
+        "required": [
+          "results"
+        ],
+        "properties": {
+          "results": {
+            "type": "array",
+            "items": {
+              "$ref": "#/components/schemas/WebSearchResult"
+            }
+          }
+        }
+      },
+      "WebSearchResult": {
+        "type": "object",
+        "required": [
+          "title",
+          "url",
+          "content"
+        ],
+        "properties": {
+          "content": {
+            "type": "string"
+          },
+          "score": {
+            "type": [
+              "number",
+              "null"
+            ],
+            "format": "double"
+          },
+          "title": {
+            "type": "string"
+          },
+          "url": {
+            "type": "string"
+          }
+        }
       }
     },
     "securitySchemes": {
@@ -25474,8 +32682,8 @@
       "description": "Store and manage chat conversation history. Conversations can be owned by users or projects and support multiple models."
     },
     {
-      "name": "prompts",
-      "description": "Manage reusable system prompt templates. Prompts can be owned by organizations, teams, projects, or users and include metadata for configuration."
+      "name": "templates",
+      "description": "Manage reusable prompt templates. Templates can be owned by organizations, teams, projects, or users and include metadata for configuration."
     },
     {
       "name": "audit-logs",
diff --git a/src/api_types/responses.rs b/src/api_types/responses.rs
index 391eb63e..c575c416 100644
--- a/src/api_types/responses.rs
+++ b/src/api_types/responses.rs
@@ -1334,12 +1334,12 @@ pub struct CreateResponsesPayload {
     #[cfg_attr(feature = "utoipa", schema(value_type = Object))]
     pub truncation: Option<serde_json::Value>,
 
-    /// Presence penalty (-2.0 to 2.0)
+    /// **Hadrian Extension:** Presence penalty (-2.0 to 2.0)
     #[validate(range(min = -2.0, max = 2.0))]
     #[serde(skip_serializing_if = "Option::is_none")]
     pub presence_penalty: Option<f64>,
 
-    /// Frequency penalty (-2.0 to 2.0)
+    /// **Hadrian Extension:** Frequency penalty (-2.0 to 2.0)
     #[validate(range(min = -2.0, max = 2.0))]
     #[serde(skip_serializing_if = "Option::is_none")]
     pub frequency_penalty: Option<f64>,

From 7a4522b4d7f4b1eaeb7fedb7d200365945667d26 Mon Sep 17 00:00:00 2001
From: ScriptSmith <ScriptSmith@users.noreply.github.com>
Date: Sun, 29 Mar 2026 18:41:11 +1000
Subject: [PATCH 3/8] Add spec

---
 ui/src/api/openapi.json | 24 +++++++++++++++++++++---
 1 file changed, 21 insertions(+), 3 deletions(-)

diff --git a/ui/src/api/openapi.json b/ui/src/api/openapi.json
index 87580f21..4b44c8f2 100644
--- a/ui/src/api/openapi.json
+++ b/ui/src/api/openapi.json
@@ -21629,6 +21629,14 @@
             ],
             "description": "Run in background"
           },
+          "frequency_penalty": {
+            "type": [
+              "number",
+              "null"
+            ],
+            "format": "double",
+            "description": "**Hadrian Extension:** Frequency penalty (-2.0 to 2.0)"
+          },
           "include": {
             "type": "array",
             "items": {
@@ -21690,6 +21698,14 @@
             },
             "description": "**Hadrian Extension:** Plugins to enable for this request"
           },
+          "presence_penalty": {
+            "type": [
+              "number",
+              "null"
+            ],
+            "format": "double",
+            "description": "**Hadrian Extension:** Presence penalty (-2.0 to 2.0)"
+          },
           "previous_response_id": {
             "type": [
               "string",
@@ -27879,10 +27895,12 @@
         ],
         "properties": {
           "current_session_id": {
-            "type": "string",
+            "type": [
+              "string",
+              "null"
+            ],
             "format": "uuid",
-            "description": "The session ID of the current request (if authenticated via session cookie).\nAllows the UI to highlight the current session and warn before self-revocation.",
-            "nullable": true
+            "description": "The session ID of the current request (if authenticated via session cookie).\nAllows the UI to highlight the current session and warn before self-revocation."
           },
           "data": {
             "type": "array",

From e293b8b52291625ff3ab6ce1f19d8a2c8d3414fd Mon Sep 17 00:00:00 2001
From: ScriptSmith <ScriptSmith@users.noreply.github.com>
Date: Sun, 29 Mar 2026 18:45:54 +1000
Subject: [PATCH 4/8] Review fixes

---
 src/api_types/responses.rs | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/src/api_types/responses.rs b/src/api_types/responses.rs
index c575c416..f31e5ab0 100644
--- a/src/api_types/responses.rs
+++ b/src/api_types/responses.rs
@@ -1481,7 +1481,10 @@ impl CreateResponsesResponse {
         let mut val = serde_json::to_value(self).unwrap_or_default();
         if let serde_json::Value::Object(ref mut map) = val {
             if self.status == Some(ResponsesResponseStatus::Completed) {
-                map.insert("completed_at".into(), serde_json::json!(self.created_at));
+                map.insert(
+                    "completed_at".into(),
+                    serde_json::json!(chrono::Utc::now().timestamp() as f64),
+                );
             }
             for (k, v) in echo_fields {
                 // Don't overwrite reasoning if the struct already has it set from conversion
@@ -1509,8 +1512,12 @@ impl CreateResponsesPayload {
                     .into_iter()
                     .map(|mut t| {
                         if let serde_json::Value::Object(ref mut obj) = t {
-                            obj.entry("strict").or_insert(serde_json::Value::Null);
-                            obj.entry("description").or_insert(serde_json::Value::Null);
+                            let is_function =
+                                obj.get("type").and_then(|v| v.as_str()) == Some("function");
+                            if is_function {
+                                obj.entry("strict").or_insert(serde_json::Value::Null);
+                                obj.entry("description").or_insert(serde_json::Value::Null);
+                            }
                         }
                         t
                     })
@@ -1624,9 +1631,14 @@ impl CreateResponsesPayload {
                 })
                 .unwrap_or(serde_json::Value::Null),
         );
+        m.insert(
+            "metadata".into(),
+            serde_json::to_value(self.metadata.clone()).unwrap_or(serde_json::Value::Null),
+        );
         m.insert("error".into(), serde_json::Value::Null);
         m.insert("incomplete_details".into(), serde_json::Value::Null);
         m.insert("max_tool_calls".into(), serde_json::Value::Null);
+        // top_logprobs is not a request parameter on the Responses API; default to 0 per spec
         m.insert("top_logprobs".into(), serde_json::json!(0));
         // Ensure reasoning is echoed (null if not configured)
         m.insert(

From f94e3f82fa4c5408c391d374f34edfdd5163bbad Mon Sep 17 00:00:00 2001
From: ScriptSmith <ScriptSmith@users.noreply.github.com>
Date: Sun, 29 Mar 2026 18:36:35 +1000
Subject: [PATCH 5/8] Update samael

---
 Cargo.lock       | 8 ++++----
 Cargo.toml       | 2 +-
 src/auth/saml.rs | 2 +-
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 3a11dc49..1bf489d7 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1201,9 +1201,9 @@ dependencies = [
 
 [[package]]
 name = "bindgen"
-version = "0.71.1"
+version = "0.72.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f58bf3d7db68cfbac37cfc485a8d711e87e064c3d0fe0435b92f7a407f9d6b3"
+checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895"
 dependencies = [
  "bitflags",
  "cexpr",
@@ -7719,9 +7719,9 @@ dependencies = [
 
 [[package]]
 name = "samael"
-version = "0.0.19"
+version = "0.0.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f20498fc95ccfe0f015d003aa86084b042cc672a9a41fa2bea4ab7d7e3239348"
+checksum = "8b010d88b2c7b2c3fc9e49f6fffa086d4c350ec50538a8082f88e446ea16c670"
 dependencies = [
  "base64 0.22.1",
  "bindgen",
diff --git a/Cargo.toml b/Cargo.toml
index 36420651..06a7696e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -361,7 +361,7 @@ opentelemetry-semantic-conventions = { version = "0.30", optional = true }
 opentelemetry_sdk = { version = "0.30", features = ["rt-tokio", "logs"], optional = true }
 redis = { version = "0.32.7", features = ["aio", "tokio-comp", "cluster-async"], optional = true }
 rust-embed = { version = "8", features = ["mime-guess", "include-exclude"], optional = true }
-samael = { version = "0.0.19", optional = true }
+samael = { version = "0.0.20", optional = true }
 schemars = { version = "0.8", optional = true }
 sqlx = { version = "0.8", features = ["runtime-tokio", "uuid", "chrono", "rust_decimal", "migrate", "json"], optional = true }
 tiktoken-rs = { version = "0.9.1", optional = true }
diff --git a/src/auth/saml.rs b/src/auth/saml.rs
index 673b5bf0..d15c95a3 100644
--- a/src/auth/saml.rs
+++ b/src/auth/saml.rs
@@ -257,7 +257,7 @@ impl SamlAuthenticator {
         let url = if self.config.sign_requests {
             let private_key = self.load_private_key()?;
             authn_request
-                .signed_redirect(&relay_state, private_key)
+                .signed_redirect(&relay_state, &private_key)
                 .map_err(|e| AuthError::Internal(format!("Failed to sign AuthnRequest: {}", e)))?
                 .ok_or_else(|| AuthError::Internal("AuthnRequest has no destination".to_string()))?
         } else {

From 0a92c8761ab3bb6d66d8ea631a130a7647d0893c Mon Sep 17 00:00:00 2001
From: ScriptSmith <ScriptSmith@users.noreply.github.com>
Date: Sun, 29 Mar 2026 19:29:36 +1000
Subject: [PATCH 6/8] Downgrade samael

---
 Cargo.lock       | 8 ++++----
 Cargo.toml       | 2 +-
 src/auth/saml.rs | 2 +-
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 1bf489d7..3a11dc49 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1201,9 +1201,9 @@ dependencies = [
 
 [[package]]
 name = "bindgen"
-version = "0.72.1"
+version = "0.71.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895"
+checksum = "5f58bf3d7db68cfbac37cfc485a8d711e87e064c3d0fe0435b92f7a407f9d6b3"
 dependencies = [
  "bitflags",
  "cexpr",
@@ -7719,9 +7719,9 @@ dependencies = [
 
 [[package]]
 name = "samael"
-version = "0.0.20"
+version = "0.0.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b010d88b2c7b2c3fc9e49f6fffa086d4c350ec50538a8082f88e446ea16c670"
+checksum = "f20498fc95ccfe0f015d003aa86084b042cc672a9a41fa2bea4ab7d7e3239348"
 dependencies = [
  "base64 0.22.1",
  "bindgen",
diff --git a/Cargo.toml b/Cargo.toml
index 06a7696e..36420651 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -361,7 +361,7 @@ opentelemetry-semantic-conventions = { version = "0.30", optional = true }
 opentelemetry_sdk = { version = "0.30", features = ["rt-tokio", "logs"], optional = true }
 redis = { version = "0.32.7", features = ["aio", "tokio-comp", "cluster-async"], optional = true }
 rust-embed = { version = "8", features = ["mime-guess", "include-exclude"], optional = true }
-samael = { version = "0.0.20", optional = true }
+samael = { version = "0.0.19", optional = true }
 schemars = { version = "0.8", optional = true }
 sqlx = { version = "0.8", features = ["runtime-tokio", "uuid", "chrono", "rust_decimal", "migrate", "json"], optional = true }
 tiktoken-rs = { version = "0.9.1", optional = true }
diff --git a/src/auth/saml.rs b/src/auth/saml.rs
index d15c95a3..673b5bf0 100644
--- a/src/auth/saml.rs
+++ b/src/auth/saml.rs
@@ -257,7 +257,7 @@ impl SamlAuthenticator {
         let url = if self.config.sign_requests {
             let private_key = self.load_private_key()?;
             authn_request
-                .signed_redirect(&relay_state, &private_key)
+                .signed_redirect(&relay_state, private_key)
                 .map_err(|e| AuthError::Internal(format!("Failed to sign AuthnRequest: {}", e)))?
                 .ok_or_else(|| AuthError::Internal("AuthnRequest has no destination".to_string()))?
         } else {

From 1c0b8419fafa4cbc85c81eee4ff3574f5e8d5418 Mon Sep 17 00:00:00 2001
From: ScriptSmith <ScriptSmith@users.noreply.github.com>
Date: Sun, 29 Mar 2026 19:49:25 +1000
Subject: [PATCH 7/8] Review fixes

---
 src/api_types/responses.rs        | 7 ++++---
 src/providers/anthropic/stream.rs | 2 ++
 src/providers/bedrock/stream.rs   | 2 ++
 src/providers/vertex/stream.rs    | 2 ++
 4 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/src/api_types/responses.rs b/src/api_types/responses.rs
index f31e5ab0..1f37734b 100644
--- a/src/api_types/responses.rs
+++ b/src/api_types/responses.rs
@@ -1633,10 +1633,11 @@ impl CreateResponsesPayload {
         );
         m.insert(
             "metadata".into(),
-            serde_json::to_value(self.metadata.clone()).unwrap_or(serde_json::Value::Null),
+            self.metadata
+                .as_ref()
+                .map(|md| serde_json::to_value(md).unwrap_or_default())
+                .unwrap_or_else(|| serde_json::json!({})),
         );
-        m.insert("error".into(), serde_json::Value::Null);
-        m.insert("incomplete_details".into(), serde_json::Value::Null);
         m.insert("max_tool_calls".into(), serde_json::Value::Null);
         // top_logprobs is not a request parameter on the Responses API; default to 0 per spec
         m.insert("top_logprobs".into(), serde_json::json!(0));
diff --git a/src/providers/anthropic/stream.rs b/src/providers/anthropic/stream.rs
index db44fd58..8f92e4a8 100644
--- a/src/providers/anthropic/stream.rs
+++ b/src/providers/anthropic/stream.rs
@@ -764,6 +764,8 @@ impl<S> AnthropicToResponsesStream<S> {
         obj.insert("status".into(), serde_json::json!(status));
         obj.insert("output".into(), output);
         obj.insert("completed_at".into(), serde_json::Value::Null);
+        obj.insert("error".into(), serde_json::Value::Null);
+        obj.insert("incomplete_details".into(), serde_json::Value::Null);
         obj.insert("usage".into(), serde_json::Value::Null);
         for (k, v) in &self.state.echo_fields {
             obj.insert(k.clone(), v.clone());
diff --git a/src/providers/bedrock/stream.rs b/src/providers/bedrock/stream.rs
index 296c9e4f..0ad718dd 100644
--- a/src/providers/bedrock/stream.rs
+++ b/src/providers/bedrock/stream.rs
@@ -607,6 +607,8 @@ impl<S> BedrockToResponsesStream<S> {
         obj.insert("status".into(), serde_json::json!(status));
         obj.insert("output".into(), output);
         obj.insert("completed_at".into(), serde_json::Value::Null);
+        obj.insert("error".into(), serde_json::Value::Null);
+        obj.insert("incomplete_details".into(), serde_json::Value::Null);
         obj.insert("usage".into(), serde_json::Value::Null);
         for (k, v) in &self.state.echo_fields {
             obj.insert(k.clone(), v.clone());
diff --git a/src/providers/vertex/stream.rs b/src/providers/vertex/stream.rs
index 401f85d9..49a9ffaa 100644
--- a/src/providers/vertex/stream.rs
+++ b/src/providers/vertex/stream.rs
@@ -574,6 +574,8 @@ impl<S> VertexToResponsesStream<S> {
         obj.insert("status".into(), serde_json::json!(status));
         obj.insert("output".into(), output);
         obj.insert("completed_at".into(), serde_json::Value::Null);
+        obj.insert("error".into(), serde_json::Value::Null);
+        obj.insert("incomplete_details".into(), serde_json::Value::Null);
         obj.insert("usage".into(), serde_json::Value::Null);
         for (k, v) in &self.state.echo_fields {
             obj.insert(k.clone(), v.clone());

From 4f12cdc8ddf75fc1b1ca958a7b8a75ba95a63603 Mon Sep 17 00:00:00 2001
From: ScriptSmith <ScriptSmith@users.noreply.github.com>
Date: Sun, 29 Mar 2026 20:05:08 +1000
Subject: [PATCH 8/8] Combine shared echo utils

---
 src/api_types/responses.rs        | 28 ++++++++++++++++++++++++++++
 src/providers/anthropic/stream.rs | 27 ++++++++-------------------
 src/providers/bedrock/stream.rs   | 27 ++++++++-------------------
 src/providers/vertex/stream.rs    | 27 ++++++++-------------------
 4 files changed, 52 insertions(+), 57 deletions(-)

diff --git a/src/api_types/responses.rs b/src/api_types/responses.rs
index 1f37734b..93da3eb2 100644
--- a/src/api_types/responses.rs
+++ b/src/api_types/responses.rs
@@ -1498,6 +1498,34 @@ impl CreateResponsesResponse {
     }
 }
 
+/// Build a Responses API `response` JSON object for streaming events.
+///
+/// Shared by all provider stream transformers (Anthropic, Bedrock, Vertex).
+pub fn build_streaming_response_json(
+    id: &str,
+    model: &str,
+    created_at: f64,
+    status: &str,
+    output: serde_json::Value,
+    echo_fields: &serde_json::Map<String, serde_json::Value>,
+) -> serde_json::Map<String, serde_json::Value> {
+    let mut obj = serde_json::Map::new();
+    obj.insert("id".into(), serde_json::json!(id));
+    obj.insert("object".into(), serde_json::json!("response"));
+    obj.insert("created_at".into(), serde_json::json!(created_at));
+    obj.insert("model".into(), serde_json::json!(model));
+    obj.insert("status".into(), serde_json::json!(status));
+    obj.insert("output".into(), output);
+    obj.insert("completed_at".into(), serde_json::Value::Null);
+    obj.insert("error".into(), serde_json::Value::Null);
+    obj.insert("incomplete_details".into(), serde_json::Value::Null);
+    obj.insert("usage".into(), serde_json::Value::Null);
+    for (k, v) in echo_fields {
+        obj.insert(k.clone(), v.clone());
+    }
+    obj
+}
+
 impl CreateResponsesPayload {
     /// Produce a JSON map of echo fields for streaming response.completed events.
     pub fn echo_fields_json(&self) -> serde_json::Map<String, serde_json::Value> {
diff --git a/src/providers/anthropic/stream.rs b/src/providers/anthropic/stream.rs
index 8f92e4a8..533bd6a8 100644
--- a/src/providers/anthropic/stream.rs
+++ b/src/providers/anthropic/stream.rs
@@ -747,30 +747,19 @@ impl<S> AnthropicToResponsesStream<S> {
         seq
     }
 
-    /// Build a response JSON object with echo fields for streaming events.
     fn build_response_json(
         &self,
         status: &str,
         output: serde_json::Value,
     ) -> serde_json::Map<String, serde_json::Value> {
-        let mut obj = serde_json::Map::new();
-        obj.insert("id".into(), serde_json::json!(self.state.response_id));
-        obj.insert("object".into(), serde_json::json!("response"));
-        obj.insert(
-            "created_at".into(),
-            serde_json::json!(Self::created_timestamp()),
-        );
-        obj.insert("model".into(), serde_json::json!(self.state.model));
-        obj.insert("status".into(), serde_json::json!(status));
-        obj.insert("output".into(), output);
-        obj.insert("completed_at".into(), serde_json::Value::Null);
-        obj.insert("error".into(), serde_json::Value::Null);
-        obj.insert("incomplete_details".into(), serde_json::Value::Null);
-        obj.insert("usage".into(), serde_json::Value::Null);
-        for (k, v) in &self.state.echo_fields {
-            obj.insert(k.clone(), v.clone());
-        }
-        obj
+        crate::api_types::responses::build_streaming_response_json(
+            &self.state.response_id,
+            &self.state.model,
+            Self::created_timestamp(),
+            status,
+            output,
+            &self.state.echo_fields,
+        )
     }
 
     /// Calculate the output index for message (accounting for reasoning if present)
diff --git a/src/providers/bedrock/stream.rs b/src/providers/bedrock/stream.rs
index 0ad718dd..989ffc4d 100644
--- a/src/providers/bedrock/stream.rs
+++ b/src/providers/bedrock/stream.rs
@@ -590,30 +590,19 @@ impl<S> BedrockToResponsesStream<S> {
         seq
     }
 
-    /// Build a response JSON object with echo fields for streaming events.
     fn build_response_json(
         &self,
         status: &str,
         output: serde_json::Value,
     ) -> serde_json::Map<String, serde_json::Value> {
-        let mut obj = serde_json::Map::new();
-        obj.insert("id".into(), serde_json::json!(self.state.response_id));
-        obj.insert("object".into(), serde_json::json!("response"));
-        obj.insert(
-            "created_at".into(),
-            serde_json::json!(Self::created_timestamp()),
-        );
-        obj.insert("model".into(), serde_json::json!(self.state.model));
-        obj.insert("status".into(), serde_json::json!(status));
-        obj.insert("output".into(), output);
-        obj.insert("completed_at".into(), serde_json::Value::Null);
-        obj.insert("error".into(), serde_json::Value::Null);
-        obj.insert("incomplete_details".into(), serde_json::Value::Null);
-        obj.insert("usage".into(), serde_json::Value::Null);
-        for (k, v) in &self.state.echo_fields {
-            obj.insert(k.clone(), v.clone());
-        }
-        obj
+        crate::api_types::responses::build_streaming_response_json(
+            &self.state.response_id,
+            &self.state.model,
+            Self::created_timestamp(),
+            status,
+            output,
+            &self.state.echo_fields,
+        )
     }
 
     /// Calculate the output index for message (accounting for reasoning if present)
diff --git a/src/providers/vertex/stream.rs b/src/providers/vertex/stream.rs
index 49a9ffaa..4acd7ee1 100644
--- a/src/providers/vertex/stream.rs
+++ b/src/providers/vertex/stream.rs
@@ -557,30 +557,19 @@ impl<S> VertexToResponsesStream<S> {
         seq
     }
 
-    /// Build a response JSON object with echo fields for streaming events.
     fn build_response_json(
         &self,
         status: &str,
         output: serde_json::Value,
     ) -> serde_json::Map<String, serde_json::Value> {
-        let mut obj = serde_json::Map::new();
-        obj.insert("id".into(), serde_json::json!(self.state.response_id));
-        obj.insert("object".into(), serde_json::json!("response"));
-        obj.insert(
-            "created_at".into(),
-            serde_json::json!(Self::created_timestamp()),
-        );
-        obj.insert("model".into(), serde_json::json!(self.state.model));
-        obj.insert("status".into(), serde_json::json!(status));
-        obj.insert("output".into(), output);
-        obj.insert("completed_at".into(), serde_json::Value::Null);
-        obj.insert("error".into(), serde_json::Value::Null);
-        obj.insert("incomplete_details".into(), serde_json::Value::Null);
-        obj.insert("usage".into(), serde_json::Value::Null);
-        for (k, v) in &self.state.echo_fields {
-            obj.insert(k.clone(), v.clone());
-        }
-        obj
+        crate::api_types::responses::build_streaming_response_json(
+            &self.state.response_id,
+            &self.state.model,
+            Self::created_timestamp(),
+            status,
+            output,
+            &self.state.echo_fields,
+        )
     }
 
     /// Parse a Vertex SSE line and generate Responses API SSE chunks
