Skip to main content

openrouter_rs/
client.rs

1use derive_builder::Builder;
2use futures_util::stream::BoxStream;
3
4#[cfg(feature = "legacy-completions")]
5use crate::api::legacy::completion;
6use crate::{
7    api::{
8        analytics, api_keys, audio, auth, byok, chat, credits, discovery, embeddings, files,
9        generation, guardrails, images, messages, models, observability, organization, presets,
10        rerank, responses, videos, workspaces,
11    },
12    error::OpenRouterError,
13    strip_option_vec_setter,
14    types::{
15        ModelCategory, PaginationOptions, SupportedParameters,
16        completion::CompletionsResponse,
17        stream::{
18            ToolAwareStream, UnifiedStream, adapt_chat_stream, adapt_messages_stream,
19            adapt_responses_stream,
20        },
21    },
22};
23
24#[derive(Debug, Clone, Builder)]
25#[builder(build_fn(error = "OpenRouterError"))]
26pub struct OpenRouterClient {
27    #[builder(
28        setter(into),
29        default = "String::from(\"https://openrouter.ai/api/v1\")"
30    )]
31    base_url: String,
32    #[builder(setter(into, strip_option), default)]
33    api_key: Option<String>,
34    #[builder(setter(into, strip_option), default)]
35    management_key: Option<String>,
36    #[builder(setter(into, strip_option), default)]
37    http_referer: Option<String>,
38    #[builder(
39        setter(into, strip_option),
40        default = "Some(String::from(\"openrouter-rs\"))"
41    )]
42    x_title: Option<String>,
43    #[builder(setter(custom), default)]
44    app_categories: Option<Vec<String>>,
45    #[builder(setter(into), default = "crate::transport::new_client()?")]
46    http_client: reqwest::Client,
47}
48
49impl OpenRouterClient {
50    pub fn builder() -> OpenRouterClientBuilder {
51        OpenRouterClientBuilder::default()
52    }
53
54    /// Sets the API key after client construction.
55    ///
56    /// # Arguments
57    ///
58    /// * `api_key` - The API key to set
59    ///
60    /// # Example
61    ///
62    /// ```
63    /// # use openrouter_rs::OpenRouterClient;
64    /// let mut client = OpenRouterClient::builder().build()?;
65    /// client.set_api_key("your_api_key");
66    /// # Ok::<(), openrouter_rs::error::OpenRouterError>(())
67    /// ```
68    pub fn set_api_key(&mut self, api_key: impl Into<String>) {
69        self.api_key = Some(api_key.into());
70    }
71
72    /// Clears the currently set API key.
73    ///
74    /// # Example
75    ///
76    /// ```
77    /// # use openrouter_rs::OpenRouterClient;
78    /// let mut client = OpenRouterClient::builder().api_key("your_api_key").build()?;
79    /// client.clear_api_key();
80    /// # Ok::<(), openrouter_rs::error::OpenRouterError>(())
81    /// ```
82    pub fn clear_api_key(&mut self) {
83        self.api_key = None;
84    }
85
86    /// Sets the management key after client construction.
87    ///
88    /// # Arguments
89    ///
90    /// * `management_key` - The management key to set
91    ///
92    /// # Example
93    ///
94    /// ```
95    /// # use openrouter_rs::OpenRouterClient;
96    /// let mut client = OpenRouterClient::builder().build()?;
97    /// client.set_management_key("your_management_key");
98    /// # Ok::<(), openrouter_rs::error::OpenRouterError>(())
99    /// ```
100    pub fn set_management_key(&mut self, management_key: impl Into<String>) {
101        self.management_key = Some(management_key.into());
102    }
103
104    /// Clears the currently set management key.
105    ///
106    /// # Example
107    ///
108    /// ```
109    /// # use openrouter_rs::OpenRouterClient;
110    /// let mut client = OpenRouterClient::builder().build()?;
111    /// client.set_management_key("your_management_key");
112    /// client.clear_management_key();
113    /// # Ok::<(), openrouter_rs::error::OpenRouterError>(())
114    /// ```
115    pub fn clear_management_key(&mut self) {
116        self.management_key = None;
117    }
118
119    /// Domain client for chat completions and chat streaming.
120    pub fn chat(&self) -> ChatClient<'_> {
121        ChatClient { client: self }
122    }
123
124    /// Domain client for Responses API operations.
125    pub fn responses(&self) -> ResponsesClient<'_> {
126        ResponsesClient { client: self }
127    }
128
129    /// Domain client for Anthropic-compatible `/messages` operations.
130    pub fn messages(&self) -> MessagesClient<'_> {
131        MessagesClient { client: self }
132    }
133
134    /// Domain client for rerank operations.
135    pub fn rerank(&self) -> RerankClient<'_> {
136        RerankClient { client: self }
137    }
138
139    /// Domain client for audio operations.
140    pub fn audio(&self) -> AudioClient<'_> {
141        AudioClient { client: self }
142    }
143
144    /// Domain client for image generation operations.
145    pub fn images(&self) -> ImagesClient<'_> {
146        ImagesClient { client: self }
147    }
148
149    /// Domain client for text-to-speech operations.
150    #[deprecated(note = "use client.audio().speech()")]
151    pub fn tts(&self) -> SpeechClient<'_> {
152        self.audio().speech()
153    }
154
155    /// Domain client for video generation operations.
156    pub fn videos(&self) -> VideosClient<'_> {
157        VideosClient { client: self }
158    }
159
160    /// Domain client for file upload, metadata, content, and deletion operations.
161    pub fn files(&self) -> FilesClient<'_> {
162        FilesClient { client: self }
163    }
164
165    /// Domain client for model/discovery/embedding operations.
166    pub fn models(&self) -> ModelsClient<'_> {
167        ModelsClient { client: self }
168    }
169
170    /// Domain client for management-governed endpoints.
171    pub fn management(&self) -> ManagementClient<'_> {
172        ManagementClient { client: self }
173    }
174
175    /// Domain client for legacy endpoint access (`legacy-completions` feature).
176    #[cfg(feature = "legacy-completions")]
177    pub fn legacy(&self) -> LegacyClient<'_> {
178        LegacyClient { client: self }
179    }
180
181    pub(crate) fn http_client(&self) -> &reqwest::Client {
182        &self.http_client
183    }
184}
185
186impl OpenRouterClientBuilder {
187    strip_option_vec_setter!(app_categories, String);
188}
189
190#[doc(hidden)]
191impl OpenRouterClient {
192    /// Creates a new API key. Requires a management API key.
193    ///
194    /// # Arguments
195    ///
196    /// * `name` - The display name for the new API key.
197    /// * `limit` - Optional credit limit for the new API key.
198    ///
199    /// # Returns
200    ///
201    /// * `Result<api_keys::ApiKey, OpenRouterError>` - The created API key.
202    ///
203    /// # Example
204    ///
205    /// ```no_run
206    /// # use openrouter_rs::OpenRouterClient;
207    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
208    /// let client = OpenRouterClient::builder().management_key("your_management_key").build()?;
209    /// let api_key = client.create_api_key("New API Key", Some(100.0)).await?;
210    /// println!("{:?}", api_key);
211    /// # Ok(())
212    /// # }
213    /// ```
214    pub async fn create_api_key(
215        &self,
216        name: &str,
217        limit: Option<f64>,
218    ) -> Result<api_keys::ApiKey, OpenRouterError> {
219        if let Some(management_key) = &self.management_key {
220            api_keys::create_api_key_with_client(
221                self.http_client(),
222                &self.base_url,
223                management_key,
224                name,
225                limit,
226            )
227            .await
228        } else {
229            Err(OpenRouterError::KeyNotConfigured)
230        }
231    }
232
233    /// Creates a new API key in the specified workspace. Requires a management API key.
234    pub async fn create_api_key_in_workspace(
235        &self,
236        name: &str,
237        limit: Option<f64>,
238        workspace_id: Option<&str>,
239    ) -> Result<api_keys::ApiKey, OpenRouterError> {
240        if let Some(management_key) = &self.management_key {
241            api_keys::create_api_key_in_workspace_with_client(
242                self.http_client(),
243                &self.base_url,
244                management_key,
245                name,
246                limit,
247                workspace_id,
248            )
249            .await
250        } else {
251            Err(OpenRouterError::KeyNotConfigured)
252        }
253    }
254
255    /// Get information on the API key associated with the current authentication session.
256    ///
257    /// # Returns
258    ///
259    /// * `Result<api_keys::ApiKeyDetails, OpenRouterError>` - The details of the current API key.
260    ///
261    /// # Example
262    ///
263    /// ```no_run
264    /// # use openrouter_rs::OpenRouterClient;
265    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
266    /// let client = OpenRouterClient::builder().api_key("your_api_key").build()?;
267    /// let api_key_details = client.get_current_api_key_info().await?;
268    /// println!("{:?}", api_key_details);
269    /// # Ok(())
270    /// # }
271    /// ```
272    pub async fn get_current_api_key_info(
273        &self,
274    ) -> Result<api_keys::ApiKeyDetails, OpenRouterError> {
275        if let Some(api_key) = &self.api_key {
276            api_keys::get_current_api_key_with_client(self.http_client(), &self.base_url, api_key)
277                .await
278        } else {
279            Err(OpenRouterError::KeyNotConfigured)
280        }
281    }
282
283    /// Deletes an API key. Requires a management API key.
284    ///
285    /// # Arguments
286    ///
287    /// * `hash` - The hash of the API key to delete.
288    ///
289    /// # Returns
290    ///
291    /// * `Result<bool, OpenRouterError>` - A boolean indicating whether the deletion was successful.
292    ///
293    /// # Example
294    ///
295    /// ```no_run
296    /// # use openrouter_rs::OpenRouterClient;
297    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
298    /// let client = OpenRouterClient::builder().management_key("your_management_key").build()?;
299    /// let success = client.delete_api_key("api_key_hash").await?;
300    /// println!("Deletion successful: {}", success);
301    /// # Ok(())
302    /// # }
303    /// ```
304    pub async fn delete_api_key(&self, hash: &str) -> Result<bool, OpenRouterError> {
305        if let Some(management_key) = &self.management_key {
306            api_keys::delete_api_key_with_client(
307                self.http_client(),
308                &self.base_url,
309                management_key,
310                hash,
311            )
312            .await
313        } else {
314            Err(OpenRouterError::KeyNotConfigured)
315        }
316    }
317
318    /// Updates an existing API key. Requires a management API key.
319    ///
320    /// # Arguments
321    ///
322    /// * `hash` - The hash of the API key to update.
323    /// * `name` - Optional new display name for the API key.
324    /// * `disabled` - Optional flag to disable the API key.
325    /// * `limit` - Optional new credit limit for the API key.
326    ///
327    /// # Returns
328    ///
329    /// * `Result<api_keys::ApiKey, OpenRouterError>` - The updated API key.
330    ///
331    /// # Example
332    ///
333    /// ```no_run
334    /// # use openrouter_rs::OpenRouterClient;
335    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
336    /// let client = OpenRouterClient::builder().management_key("your_management_key").build()?;
337    /// let updated_api_key = client.update_api_key("api_key_hash", Some("Updated Name".to_string()), Some(false), Some(200.0)).await?;
338    /// println!("{:?}", updated_api_key);
339    /// # Ok(())
340    /// # }
341    /// ```
342    pub async fn update_api_key(
343        &self,
344        hash: &str,
345        name: Option<String>,
346        disabled: Option<bool>,
347        limit: Option<f64>,
348    ) -> Result<api_keys::ApiKey, OpenRouterError> {
349        if let Some(management_key) = &self.management_key {
350            api_keys::update_api_key_with_client(
351                self.http_client(),
352                &self.base_url,
353                management_key,
354                hash,
355                name,
356                disabled,
357                limit,
358            )
359            .await
360        } else {
361            Err(OpenRouterError::KeyNotConfigured)
362        }
363    }
364
365    async fn list_api_keys_paginated(
366        &self,
367        pagination: Option<PaginationOptions>,
368        include_disabled: Option<bool>,
369    ) -> Result<Vec<api_keys::ApiKey>, OpenRouterError> {
370        if let Some(management_key) = &self.management_key {
371            api_keys::list_api_keys_with_client(
372                self.http_client(),
373                &self.base_url,
374                management_key,
375                pagination,
376                include_disabled,
377            )
378            .await
379        } else {
380            Err(OpenRouterError::KeyNotConfigured)
381        }
382    }
383
384    async fn list_api_keys_in_workspace_paginated(
385        &self,
386        pagination: Option<PaginationOptions>,
387        include_disabled: Option<bool>,
388        workspace_id: Option<&str>,
389    ) -> Result<Vec<api_keys::ApiKey>, OpenRouterError> {
390        if let Some(management_key) = &self.management_key {
391            api_keys::list_api_keys_in_workspace_with_client(
392                self.http_client(),
393                &self.base_url,
394                management_key,
395                pagination,
396                include_disabled,
397                workspace_id,
398            )
399            .await
400        } else {
401            Err(OpenRouterError::KeyNotConfigured)
402        }
403    }
404
405    /// Returns details about a specific API key. Requires a management API key.
406    ///
407    /// # Arguments
408    ///
409    /// * `hash` - The hash of the API key to retrieve.
410    ///
411    /// # Returns
412    ///
413    /// * `Result<api_keys::ApiKey, OpenRouterError>` - The details of the specified API key.
414    ///
415    /// # Example
416    ///
417    /// ```no_run
418    /// # use openrouter_rs::OpenRouterClient;
419    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
420    /// let client = OpenRouterClient::builder().management_key("your_management_key").build()?;
421    /// let api_key = client.get_api_key("api_key_hash").await?;
422    /// println!("{:?}", api_key);
423    /// # Ok(())
424    /// # }
425    /// ```
426    pub async fn get_api_key(&self, hash: &str) -> Result<api_keys::ApiKey, OpenRouterError> {
427        if let Some(management_key) = &self.management_key {
428            api_keys::get_api_key_with_client(
429                self.http_client(),
430                &self.base_url,
431                management_key,
432                hash,
433            )
434            .await
435        } else {
436            Err(OpenRouterError::KeyNotConfigured)
437        }
438    }
439
440    /// Create an authorization code for PKCE flow (`POST /auth/keys/code`).
441    ///
442    /// # Arguments
443    ///
444    /// * `request` - The auth-code creation request built with `CreateAuthCodeRequest::builder()`.
445    ///
446    /// # Returns
447    ///
448    /// * `Result<auth::AuthCodeData, OpenRouterError>` - The created authorization code payload.
449    ///
450    /// # Example
451    ///
452    /// ```no_run
453    /// # use openrouter_rs::{OpenRouterClient, api::auth};
454    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
455    /// let client = OpenRouterClient::builder().api_key("your_api_key").build()?;
456    ///
457    /// let create = auth::CreateAuthCodeRequest::builder()
458    ///     .callback_url("https://myapp.com/auth/callback")
459    ///     .code_challenge("E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM")
460    ///     .code_challenge_method(auth::CodeChallengeMethod::S256)
461    ///     .build()?;
462    ///
463    /// let auth_code = client.create_auth_code(&create).await?;
464    ///
465    /// let exchanged = client
466    ///     .exchange_code_for_api_key(
467    ///         &auth_code.id,
468    ///         Some("your_pkce_code_verifier"),
469    ///         Some(auth::CodeChallengeMethod::S256),
470    ///     )
471    ///     .await?;
472    ///
473    /// println!("New key: {}", exchanged.key);
474    /// # Ok(())
475    /// # }
476    /// ```
477    pub async fn create_auth_code(
478        &self,
479        request: &auth::CreateAuthCodeRequest,
480    ) -> Result<auth::AuthCodeData, OpenRouterError> {
481        if let Some(api_key) = &self.api_key {
482            auth::create_auth_code_with_client(self.http_client(), &self.base_url, api_key, request)
483                .await
484        } else {
485            Err(OpenRouterError::KeyNotConfigured)
486        }
487    }
488
489    /// List guardrails (`GET /guardrails`). Requires a management key.
490    pub async fn list_guardrails(
491        &self,
492        pagination: Option<PaginationOptions>,
493    ) -> Result<guardrails::GuardrailListResponse, OpenRouterError> {
494        if let Some(management_key) = &self.management_key {
495            guardrails::list_guardrails_with_client(
496                self.http_client(),
497                &self.base_url,
498                management_key,
499                pagination,
500            )
501            .await
502        } else {
503            Err(OpenRouterError::KeyNotConfigured)
504        }
505    }
506
507    /// List guardrails scoped to a workspace (`GET /guardrails?workspace_id=...`).
508    pub async fn list_guardrails_in_workspace(
509        &self,
510        pagination: Option<PaginationOptions>,
511        workspace_id: Option<&str>,
512    ) -> Result<guardrails::GuardrailListResponse, OpenRouterError> {
513        if let Some(management_key) = &self.management_key {
514            guardrails::list_guardrails_in_workspace_with_client(
515                self.http_client(),
516                &self.base_url,
517                management_key,
518                pagination,
519                workspace_id,
520            )
521            .await
522        } else {
523            Err(OpenRouterError::KeyNotConfigured)
524        }
525    }
526
527    /// Create a guardrail (`POST /guardrails`). Requires a management key.
528    pub async fn create_guardrail(
529        &self,
530        request: &guardrails::CreateGuardrailRequest,
531    ) -> Result<guardrails::Guardrail, OpenRouterError> {
532        if let Some(management_key) = &self.management_key {
533            guardrails::create_guardrail_with_client(
534                self.http_client(),
535                &self.base_url,
536                management_key,
537                request,
538            )
539            .await
540        } else {
541            Err(OpenRouterError::KeyNotConfigured)
542        }
543    }
544
545    /// Get a guardrail by ID (`GET /guardrails/{id}`). Requires a management key.
546    pub async fn get_guardrail(&self, id: &str) -> Result<guardrails::Guardrail, OpenRouterError> {
547        if let Some(management_key) = &self.management_key {
548            guardrails::get_guardrail_with_client(
549                self.http_client(),
550                &self.base_url,
551                management_key,
552                id,
553            )
554            .await
555        } else {
556            Err(OpenRouterError::KeyNotConfigured)
557        }
558    }
559
560    /// Update a guardrail (`PATCH /guardrails/{id}`). Requires a management key.
561    pub async fn update_guardrail(
562        &self,
563        id: &str,
564        request: &guardrails::UpdateGuardrailRequest,
565    ) -> Result<guardrails::Guardrail, OpenRouterError> {
566        if let Some(management_key) = &self.management_key {
567            guardrails::update_guardrail_with_client(
568                self.http_client(),
569                &self.base_url,
570                management_key,
571                id,
572                request,
573            )
574            .await
575        } else {
576            Err(OpenRouterError::KeyNotConfigured)
577        }
578    }
579
580    /// Delete a guardrail (`DELETE /guardrails/{id}`). Requires a management key.
581    pub async fn delete_guardrail(&self, id: &str) -> Result<bool, OpenRouterError> {
582        if let Some(management_key) = &self.management_key {
583            guardrails::delete_guardrail_with_client(
584                self.http_client(),
585                &self.base_url,
586                management_key,
587                id,
588            )
589            .await
590        } else {
591            Err(OpenRouterError::KeyNotConfigured)
592        }
593    }
594
595    /// List key assignments for a guardrail (`GET /guardrails/{id}/assignments/keys`).
596    pub async fn list_guardrail_key_assignments(
597        &self,
598        id: &str,
599        pagination: Option<PaginationOptions>,
600    ) -> Result<guardrails::GuardrailKeyAssignmentsResponse, OpenRouterError> {
601        if let Some(management_key) = &self.management_key {
602            guardrails::list_guardrail_key_assignments_with_client(
603                self.http_client(),
604                &self.base_url,
605                management_key,
606                id,
607                pagination,
608            )
609            .await
610        } else {
611            Err(OpenRouterError::KeyNotConfigured)
612        }
613    }
614
615    /// Bulk assign key hashes to a guardrail (`POST /guardrails/{id}/assignments/keys`).
616    pub async fn bulk_assign_keys_to_guardrail(
617        &self,
618        id: &str,
619        request: &guardrails::BulkKeyAssignmentRequest,
620    ) -> Result<guardrails::AssignedCountResponse, OpenRouterError> {
621        if let Some(management_key) = &self.management_key {
622            guardrails::bulk_assign_keys_to_guardrail_with_client(
623                self.http_client(),
624                &self.base_url,
625                management_key,
626                id,
627                request,
628            )
629            .await
630        } else {
631            Err(OpenRouterError::KeyNotConfigured)
632        }
633    }
634
635    /// Bulk unassign key hashes from a guardrail (`POST /guardrails/{id}/assignments/keys/remove`).
636    pub async fn bulk_unassign_keys_from_guardrail(
637        &self,
638        id: &str,
639        request: &guardrails::BulkKeyAssignmentRequest,
640    ) -> Result<guardrails::UnassignedCountResponse, OpenRouterError> {
641        if let Some(management_key) = &self.management_key {
642            guardrails::bulk_unassign_keys_from_guardrail_with_client(
643                self.http_client(),
644                &self.base_url,
645                management_key,
646                id,
647                request,
648            )
649            .await
650        } else {
651            Err(OpenRouterError::KeyNotConfigured)
652        }
653    }
654
655    /// List member assignments for a guardrail (`GET /guardrails/{id}/assignments/members`).
656    pub async fn list_guardrail_member_assignments(
657        &self,
658        id: &str,
659        pagination: Option<PaginationOptions>,
660    ) -> Result<guardrails::GuardrailMemberAssignmentsResponse, OpenRouterError> {
661        if let Some(management_key) = &self.management_key {
662            guardrails::list_guardrail_member_assignments_with_client(
663                self.http_client(),
664                &self.base_url,
665                management_key,
666                id,
667                pagination,
668            )
669            .await
670        } else {
671            Err(OpenRouterError::KeyNotConfigured)
672        }
673    }
674
675    /// Bulk assign members to a guardrail (`POST /guardrails/{id}/assignments/members`).
676    pub async fn bulk_assign_members_to_guardrail(
677        &self,
678        id: &str,
679        request: &guardrails::BulkMemberAssignmentRequest,
680    ) -> Result<guardrails::AssignedCountResponse, OpenRouterError> {
681        if let Some(management_key) = &self.management_key {
682            guardrails::bulk_assign_members_to_guardrail_with_client(
683                self.http_client(),
684                &self.base_url,
685                management_key,
686                id,
687                request,
688            )
689            .await
690        } else {
691            Err(OpenRouterError::KeyNotConfigured)
692        }
693    }
694
695    /// Bulk unassign members from a guardrail (`POST /guardrails/{id}/assignments/members/remove`).
696    pub async fn bulk_unassign_members_from_guardrail(
697        &self,
698        id: &str,
699        request: &guardrails::BulkMemberAssignmentRequest,
700    ) -> Result<guardrails::UnassignedCountResponse, OpenRouterError> {
701        if let Some(management_key) = &self.management_key {
702            guardrails::bulk_unassign_members_from_guardrail_with_client(
703                self.http_client(),
704                &self.base_url,
705                management_key,
706                id,
707                request,
708            )
709            .await
710        } else {
711            Err(OpenRouterError::KeyNotConfigured)
712        }
713    }
714
715    /// List all key assignments (`GET /guardrails/assignments/keys`). Requires a management key.
716    pub async fn list_key_assignments(
717        &self,
718        pagination: Option<PaginationOptions>,
719    ) -> Result<guardrails::GuardrailKeyAssignmentsResponse, OpenRouterError> {
720        if let Some(management_key) = &self.management_key {
721            guardrails::list_key_assignments_with_client(
722                self.http_client(),
723                &self.base_url,
724                management_key,
725                pagination,
726            )
727            .await
728        } else {
729            Err(OpenRouterError::KeyNotConfigured)
730        }
731    }
732
733    /// List all member assignments (`GET /guardrails/assignments/members`). Requires a management key.
734    pub async fn list_member_assignments(
735        &self,
736        pagination: Option<PaginationOptions>,
737    ) -> Result<guardrails::GuardrailMemberAssignmentsResponse, OpenRouterError> {
738        if let Some(management_key) = &self.management_key {
739            guardrails::list_member_assignments_with_client(
740                self.http_client(),
741                &self.base_url,
742                management_key,
743                pagination,
744            )
745            .await
746        } else {
747            Err(OpenRouterError::KeyNotConfigured)
748        }
749    }
750
751    /// Exchange an authorization code from the PKCE flow for a user-controlled API key.
752    ///
753    /// # Arguments
754    ///
755    /// * `code` - The authorization code received from the OAuth redirect.
756    /// * `code_verifier` - The code verifier if code_challenge was used in the authorization request.
757    /// * `code_challenge_method` - The method used to generate the code challenge.
758    ///
759    /// # Returns
760    ///
761    /// * `Result<auth::AuthResponse, OpenRouterError>` - The API key and user ID associated with the API key.
762    ///
763    /// # Example
764    ///
765    /// ```no_run
766    /// # use openrouter_rs::{OpenRouterClient, api::auth};
767    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
768    /// let client = OpenRouterClient::builder().api_key("your_api_key").build()?;
769    /// let auth_response = client.exchange_code_for_api_key(
770    ///     "auth_code",
771    ///     Some("code_verifier"),
772    ///     Some(auth::CodeChallengeMethod::S256),
773    /// ).await?;
774    /// println!("{:?}", auth_response);
775    /// # Ok(())
776    /// # }
777    /// ```
778    pub async fn exchange_code_for_api_key(
779        &self,
780        code: &str,
781        code_verifier: Option<&str>,
782        code_challenge_method: Option<auth::CodeChallengeMethod>,
783    ) -> Result<auth::AuthResponse, OpenRouterError> {
784        auth::exchange_code_for_api_key_with_client(
785            self.http_client(),
786            &self.base_url,
787            code,
788            code_verifier,
789            code_challenge_method,
790        )
791        .await
792    }
793
794    /// Send a chat completion request to a selected model.
795    ///
796    /// # Arguments
797    ///
798    /// * `request` - The chat completion request built using ChatCompletionRequest::builder().
799    ///
800    /// # Returns
801    ///
802    /// * `Result<chat::ChatCompletionResponse, OpenRouterError>` - The response from the chat completion request.
803    ///
804    /// # Example
805    ///
806    /// ```no_run
807    /// # use openrouter_rs::{OpenRouterClient, api::chat::{self, Message}, types::Role};
808    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
809    /// let client = OpenRouterClient::builder().api_key("your_api_key").build()?;
810    /// let request = chat::ChatCompletionRequest::builder()
811    ///     .model("deepseek/deepseek-chat-v3-0324:free")
812    ///     .messages(vec![Message::new(Role::User, "What is the meaning of life?")])
813    ///     .max_tokens(100)
814    ///     .temperature(0.7)
815    ///     .build()?;
816    /// let response = client.send_chat_completion(&request).await?;
817    /// println!("{:?}", response);
818    /// # Ok(())
819    /// # }
820    /// ```
821    pub async fn send_chat_completion(
822        &self,
823        request: &chat::ChatCompletionRequest,
824    ) -> Result<CompletionsResponse, OpenRouterError> {
825        if let Some(api_key) = &self.api_key {
826            chat::send_chat_completion_with_client(
827                self.http_client(),
828                &self.base_url,
829                api_key,
830                &self.x_title,
831                &self.http_referer,
832                &self.app_categories,
833                request,
834            )
835            .await
836        } else {
837            Err(OpenRouterError::KeyNotConfigured)
838        }
839    }
840
841    /// Streams chat completion events from a selected model.
842    ///
843    /// # Arguments
844    ///
845    /// * `request` - The chat completion request built using ChatCompletionRequest::builder().
846    ///
847    /// # Returns
848    ///
849    /// * `Result<BoxStream<'static, Result<CompletionsResponse, OpenRouterError>>, OpenRouterError>` - A stream of chat completion events or an error.
850    ///
851    /// # Example
852    ///
853    /// ```no_run
854    /// # use futures_util::StreamExt;
855    /// # use openrouter_rs::{OpenRouterClient, api::chat::{self, Message}, types::Role};
856    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
857    /// let client = OpenRouterClient::builder().api_key("your_api_key").build()?;
858    /// let request = chat::ChatCompletionRequest::builder()
859    ///     .model("deepseek/deepseek-chat-v3-0324:free")
860    ///     .messages(vec![Message::new(Role::User, "Tell me a joke.")])
861    ///     .max_tokens(50)
862    ///     .temperature(0.5)
863    ///     .build()?;
864    /// let mut stream = client.stream_chat_completion(&request).await?;
865    /// while let Some(event) = stream.next().await {
866    ///     match event {
867    ///         Ok(event) => println!("{:?}", event),
868    ///         Err(e) => eprintln!("Error: {:?}", e),
869    ///     }
870    /// }
871    /// # Ok(())
872    /// # }
873    /// ```
874    pub async fn stream_chat_completion(
875        &self,
876        request: &chat::ChatCompletionRequest,
877    ) -> Result<BoxStream<'static, Result<CompletionsResponse, OpenRouterError>>, OpenRouterError>
878    {
879        if let Some(api_key) = &self.api_key {
880            chat::stream_chat_completion_with_client(
881                self.http_client(),
882                &self.base_url,
883                api_key,
884                &self.x_title,
885                &self.http_referer,
886                &self.app_categories,
887                request,
888            )
889            .await
890        } else {
891            Err(OpenRouterError::KeyNotConfigured)
892        }
893    }
894
895    /// Streams chat completion events with tool-call-aware processing.
896    ///
897    /// Returns a [`ToolAwareStream`] that yields [`StreamEvent`](crate::types::stream::StreamEvent)
898    /// values. Content and reasoning deltas are forwarded immediately, while
899    /// tool call fragments are accumulated internally and emitted as complete
900    /// [`ToolCall`](crate::types::completion::ToolCall) objects in the final
901    /// [`StreamEvent::Done`](crate::types::stream::StreamEvent::Done) event.
902    ///
903    /// This is the recommended way to stream responses when using tool calling.
904    ///
905    /// # Arguments
906    ///
907    /// * `request` - The chat completion request (should include tools).
908    ///
909    /// # Returns
910    ///
911    /// * `Result<ToolAwareStream, OpenRouterError>` - A stream of [`StreamEvent`](crate::types::stream::StreamEvent) values.
912    ///
913    /// # Example
914    ///
915    /// ```no_run
916    /// use futures_util::StreamExt;
917    /// use openrouter_rs::types::stream::StreamEvent;
918    ///
919    /// # async fn example(client: openrouter_rs::OpenRouterClient, request: openrouter_rs::api::chat::ChatCompletionRequest) -> Result<(), Box<dyn std::error::Error>> {
920    /// let mut stream = client.stream_chat_completion_tool_aware(&request).await?;
921    ///
922    /// while let Some(event) = stream.next().await {
923    ///     match event {
924    ///         StreamEvent::ContentDelta(text) => print!("{}", text),
925    ///         StreamEvent::Done { tool_calls, .. } => {
926    ///             for tc in &tool_calls {
927    ///                 println!("Tool call: {}", tc.name());
928    ///             }
929    ///         },
930    ///         _ => {}
931    ///     }
932    /// }
933    /// # Ok(())
934    /// # }
935    /// ```
936    pub async fn stream_chat_completion_tool_aware(
937        &self,
938        request: &chat::ChatCompletionRequest,
939    ) -> Result<ToolAwareStream, OpenRouterError> {
940        let raw_stream = self.stream_chat_completion(request).await?;
941        Ok(ToolAwareStream::new(raw_stream))
942    }
943
944    /// Stream chat completion events through the unified stream abstraction.
945    pub async fn stream_chat_completion_unified(
946        &self,
947        request: &chat::ChatCompletionRequest,
948    ) -> Result<UnifiedStream, OpenRouterError> {
949        let raw_stream = self.stream_chat_completion(request).await?;
950        Ok(adapt_chat_stream(raw_stream))
951    }
952
953    /// Create a non-streaming response using the OpenRouter Responses API.
954    ///
955    /// # Arguments
956    ///
957    /// * `request` - The responses request built using `ResponsesRequest::builder()`.
958    ///
959    /// # Returns
960    ///
961    /// * `Result<responses::ResponsesResponse, OpenRouterError>` - The response payload.
962    pub async fn create_response(
963        &self,
964        request: &responses::ResponsesRequest,
965    ) -> Result<responses::ResponsesResponse, OpenRouterError> {
966        if let Some(api_key) = &self.api_key {
967            responses::create_response_with_client(
968                self.http_client(),
969                &self.base_url,
970                api_key,
971                &self.x_title,
972                &self.http_referer,
973                &self.app_categories,
974                request,
975            )
976            .await
977        } else {
978            Err(OpenRouterError::KeyNotConfigured)
979        }
980    }
981
982    /// Stream response events from the OpenRouter Responses API.
983    ///
984    /// # Arguments
985    ///
986    /// * `request` - The responses request built using `ResponsesRequest::builder()`.
987    ///
988    /// # Returns
989    ///
990    /// * `Result<BoxStream<'static, Result<responses::ResponsesStreamEvent, OpenRouterError>>, OpenRouterError>` - A stream of response events.
991    pub async fn stream_response(
992        &self,
993        request: &responses::ResponsesRequest,
994    ) -> Result<
995        BoxStream<'static, Result<responses::ResponsesStreamEvent, OpenRouterError>>,
996        OpenRouterError,
997    > {
998        if let Some(api_key) = &self.api_key {
999            responses::stream_response_with_client(
1000                self.http_client(),
1001                &self.base_url,
1002                api_key,
1003                &self.x_title,
1004                &self.http_referer,
1005                &self.app_categories,
1006                request,
1007            )
1008            .await
1009        } else {
1010            Err(OpenRouterError::KeyNotConfigured)
1011        }
1012    }
1013
1014    /// Stream Responses API events through the unified stream abstraction.
1015    pub async fn stream_response_unified(
1016        &self,
1017        request: &responses::ResponsesRequest,
1018    ) -> Result<UnifiedStream, OpenRouterError> {
1019        let raw_stream = self.stream_response(request).await?;
1020        Ok(adapt_responses_stream(raw_stream))
1021    }
1022
1023    /// Create a non-streaming message using the Anthropic-compatible `/messages` API.
1024    pub async fn create_message(
1025        &self,
1026        request: &messages::AnthropicMessagesRequest,
1027    ) -> Result<messages::AnthropicMessagesResponse, OpenRouterError> {
1028        if let Some(api_key) = &self.api_key {
1029            messages::create_message_with_client(
1030                self.http_client(),
1031                &self.base_url,
1032                api_key,
1033                &self.x_title,
1034                &self.http_referer,
1035                &self.app_categories,
1036                request,
1037            )
1038            .await
1039        } else {
1040            Err(OpenRouterError::KeyNotConfigured)
1041        }
1042    }
1043
1044    /// Stream SSE events from the Anthropic-compatible `/messages` API.
1045    pub async fn stream_messages(
1046        &self,
1047        request: &messages::AnthropicMessagesRequest,
1048    ) -> Result<
1049        BoxStream<'static, Result<messages::AnthropicMessagesSseEvent, OpenRouterError>>,
1050        OpenRouterError,
1051    > {
1052        if let Some(api_key) = &self.api_key {
1053            messages::stream_messages_with_client(
1054                self.http_client(),
1055                &self.base_url,
1056                api_key,
1057                &self.x_title,
1058                &self.http_referer,
1059                &self.app_categories,
1060                request,
1061            )
1062            .await
1063        } else {
1064            Err(OpenRouterError::KeyNotConfigured)
1065        }
1066    }
1067
1068    /// Stream Messages API events through the unified stream abstraction.
1069    pub async fn stream_messages_unified(
1070        &self,
1071        request: &messages::AnthropicMessagesRequest,
1072    ) -> Result<UnifiedStream, OpenRouterError> {
1073        let raw_stream = self.stream_messages(request).await?;
1074        Ok(adapt_messages_stream(raw_stream))
1075    }
1076
1077    /// Create or update a preset from a chat-completions request body.
1078    ///
1079    /// Equivalent to `POST /presets/{slug}/chat/completions`.
1080    pub async fn create_chat_completion_preset(
1081        &self,
1082        slug: &str,
1083        request: &chat::ChatCompletionRequest,
1084    ) -> Result<presets::PresetWithDesignatedVersion, OpenRouterError> {
1085        if let Some(management_key) = &self.management_key {
1086            presets::create_chat_completion_preset_with_client(
1087                self.http_client(),
1088                &self.base_url,
1089                management_key,
1090                slug,
1091                request,
1092            )
1093            .await
1094        } else {
1095            Err(OpenRouterError::KeyNotConfigured)
1096        }
1097    }
1098
1099    /// Create or update a preset from a Responses API request body.
1100    ///
1101    /// Equivalent to `POST /presets/{slug}/responses`.
1102    pub async fn create_response_preset(
1103        &self,
1104        slug: &str,
1105        request: &responses::ResponsesRequest,
1106    ) -> Result<presets::PresetWithDesignatedVersion, OpenRouterError> {
1107        if let Some(management_key) = &self.management_key {
1108            presets::create_response_preset_with_client(
1109                self.http_client(),
1110                &self.base_url,
1111                management_key,
1112                slug,
1113                request,
1114            )
1115            .await
1116        } else {
1117            Err(OpenRouterError::KeyNotConfigured)
1118        }
1119    }
1120
1121    /// Create or update a preset from an Anthropic-compatible Messages request body.
1122    ///
1123    /// Equivalent to `POST /presets/{slug}/messages`.
1124    pub async fn create_message_preset(
1125        &self,
1126        slug: &str,
1127        request: &messages::AnthropicMessagesRequest,
1128    ) -> Result<presets::PresetWithDesignatedVersion, OpenRouterError> {
1129        if let Some(management_key) = &self.management_key {
1130            presets::create_message_preset_with_client(
1131                self.http_client(),
1132                &self.base_url,
1133                management_key,
1134                slug,
1135                request,
1136            )
1137            .await
1138        } else {
1139            Err(OpenRouterError::KeyNotConfigured)
1140        }
1141    }
1142
1143    /// List presets for the configured management key.
1144    pub async fn list_presets(
1145        &self,
1146        pagination: Option<PaginationOptions>,
1147    ) -> Result<presets::ListPresetsResponse, OpenRouterError> {
1148        if let Some(management_key) = &self.management_key {
1149            presets::list_presets_with_client(
1150                self.http_client(),
1151                &self.base_url,
1152                management_key,
1153                pagination,
1154            )
1155            .await
1156        } else {
1157            Err(OpenRouterError::KeyNotConfigured)
1158        }
1159    }
1160
1161    /// Get one preset with its designated version.
1162    pub async fn get_preset(
1163        &self,
1164        slug: &str,
1165    ) -> Result<presets::PresetWithDesignatedVersion, OpenRouterError> {
1166        if let Some(management_key) = &self.management_key {
1167            presets::get_preset_with_client(
1168                self.http_client(),
1169                &self.base_url,
1170                management_key,
1171                slug,
1172            )
1173            .await
1174        } else {
1175            Err(OpenRouterError::KeyNotConfigured)
1176        }
1177    }
1178
1179    /// List versions for one preset.
1180    pub async fn list_preset_versions(
1181        &self,
1182        slug: &str,
1183        pagination: Option<PaginationOptions>,
1184    ) -> Result<presets::ListPresetVersionsResponse, OpenRouterError> {
1185        if let Some(management_key) = &self.management_key {
1186            presets::list_preset_versions_with_client(
1187                self.http_client(),
1188                &self.base_url,
1189                management_key,
1190                slug,
1191                pagination,
1192            )
1193            .await
1194        } else {
1195            Err(OpenRouterError::KeyNotConfigured)
1196        }
1197    }
1198
1199    /// Get a specific preset version.
1200    pub async fn get_preset_version(
1201        &self,
1202        slug: &str,
1203        version: &str,
1204    ) -> Result<presets::PresetDesignatedVersion, OpenRouterError> {
1205        if let Some(management_key) = &self.management_key {
1206            presets::get_preset_version_with_client(
1207                self.http_client(),
1208                &self.base_url,
1209                management_key,
1210                slug,
1211                version,
1212            )
1213            .await
1214        } else {
1215            Err(OpenRouterError::KeyNotConfigured)
1216        }
1217    }
1218
1219    /// Submit an embeddings request.
1220    ///
1221    /// # Arguments
1222    ///
1223    /// * `request` - The embeddings request built using `EmbeddingRequest::builder()`.
1224    ///
1225    /// # Returns
1226    ///
1227    /// * `Result<embeddings::EmbeddingResponse, OpenRouterError>` - The embeddings response.
1228    pub async fn create_embedding(
1229        &self,
1230        request: &embeddings::EmbeddingRequest,
1231    ) -> Result<embeddings::EmbeddingResponse, OpenRouterError> {
1232        if let Some(api_key) = &self.api_key {
1233            embeddings::create_embedding_with_client(
1234                self.http_client(),
1235                &self.base_url,
1236                api_key,
1237                &self.x_title,
1238                &self.http_referer,
1239                &self.app_categories,
1240                request,
1241            )
1242            .await
1243        } else {
1244            Err(OpenRouterError::KeyNotConfigured)
1245        }
1246    }
1247
1248    /// Submit a rerank request.
1249    pub async fn create_rerank(
1250        &self,
1251        request: &rerank::RerankRequest,
1252    ) -> Result<rerank::RerankResponse, OpenRouterError> {
1253        if let Some(api_key) = &self.api_key {
1254            rerank::create_rerank_with_client(
1255                self.http_client(),
1256                &self.base_url,
1257                api_key,
1258                &self.x_title,
1259                &self.http_referer,
1260                &self.app_categories,
1261                request,
1262            )
1263            .await
1264        } else {
1265            Err(OpenRouterError::KeyNotConfigured)
1266        }
1267    }
1268
1269    /// Submit a speech request and return raw audio bytes.
1270    pub async fn create_speech(
1271        &self,
1272        request: &audio::SpeechRequest,
1273    ) -> Result<Vec<u8>, OpenRouterError> {
1274        if let Some(api_key) = &self.api_key {
1275            audio::create_speech_with_client(
1276                self.http_client(),
1277                &self.base_url,
1278                api_key,
1279                &self.x_title,
1280                &self.http_referer,
1281                &self.app_categories,
1282                request,
1283            )
1284            .await
1285        } else {
1286            Err(OpenRouterError::KeyNotConfigured)
1287        }
1288    }
1289
1290    /// Submit an audio transcription request.
1291    pub async fn create_transcription(
1292        &self,
1293        request: &audio::TranscriptionRequest,
1294    ) -> Result<audio::TranscriptionResponse, OpenRouterError> {
1295        if let Some(api_key) = &self.api_key {
1296            audio::create_transcription_with_client(
1297                self.http_client(),
1298                &self.base_url,
1299                api_key,
1300                &self.x_title,
1301                &self.http_referer,
1302                &self.app_categories,
1303                request,
1304            )
1305            .await
1306        } else {
1307            Err(OpenRouterError::KeyNotConfigured)
1308        }
1309    }
1310
1311    /// Submit a text-to-speech request and return raw audio bytes.
1312    #[deprecated(note = "use create_speech")]
1313    pub async fn create_tts(
1314        &self,
1315        request: &audio::SpeechRequest,
1316    ) -> Result<Vec<u8>, OpenRouterError> {
1317        self.create_speech(request).await
1318    }
1319
1320    /// Submit an image generation request.
1321    pub async fn create_image_generation(
1322        &self,
1323        request: &images::ImageGenerationRequest,
1324    ) -> Result<images::ImageGenerationResponse, OpenRouterError> {
1325        if let Some(api_key) = &self.api_key {
1326            images::create_image_generation_with_client(
1327                self.http_client(),
1328                &self.base_url,
1329                api_key,
1330                &self.x_title,
1331                &self.http_referer,
1332                &self.app_categories,
1333                request,
1334            )
1335            .await
1336        } else {
1337            Err(OpenRouterError::KeyNotConfigured)
1338        }
1339    }
1340
1341    /// Stream image generation events.
1342    pub async fn stream_image_generation(
1343        &self,
1344        request: &images::ImageGenerationRequest,
1345    ) -> Result<
1346        BoxStream<'static, Result<images::ImageStreamingResponse, OpenRouterError>>,
1347        OpenRouterError,
1348    > {
1349        if let Some(api_key) = &self.api_key {
1350            images::stream_image_generation_with_client(
1351                self.http_client(),
1352                &self.base_url,
1353                api_key,
1354                &self.x_title,
1355                &self.http_referer,
1356                &self.app_categories,
1357                request,
1358            )
1359            .await
1360        } else {
1361            Err(OpenRouterError::KeyNotConfigured)
1362        }
1363    }
1364
1365    /// List all available image generation models.
1366    pub async fn list_image_models(&self) -> Result<Vec<images::ImageModel>, OpenRouterError> {
1367        if let Some(api_key) = &self.api_key {
1368            images::list_image_models_with_client(self.http_client(), &self.base_url, api_key).await
1369        } else {
1370            Err(OpenRouterError::KeyNotConfigured)
1371        }
1372    }
1373
1374    /// List provider endpoints for one image generation model.
1375    pub async fn list_image_model_endpoints(
1376        &self,
1377        author: &str,
1378        slug: &str,
1379    ) -> Result<images::ImageModelEndpointsResponse, OpenRouterError> {
1380        if let Some(api_key) = &self.api_key {
1381            images::list_image_model_endpoints_with_client(
1382                self.http_client(),
1383                &self.base_url,
1384                api_key,
1385                author,
1386                slug,
1387            )
1388            .await
1389        } else {
1390            Err(OpenRouterError::KeyNotConfigured)
1391        }
1392    }
1393
1394    /// Submit a video generation request.
1395    pub async fn create_video_generation(
1396        &self,
1397        request: &videos::VideoGenerationRequest,
1398    ) -> Result<videos::VideoGenerationResponse, OpenRouterError> {
1399        if let Some(api_key) = &self.api_key {
1400            videos::create_video_generation_with_client(
1401                self.http_client(),
1402                &self.base_url,
1403                api_key,
1404                &self.x_title,
1405                &self.http_referer,
1406                &self.app_categories,
1407                request,
1408            )
1409            .await
1410        } else {
1411            Err(OpenRouterError::KeyNotConfigured)
1412        }
1413    }
1414
1415    /// List all available video generation models.
1416    pub async fn list_video_models(&self) -> Result<Vec<videos::VideoModel>, OpenRouterError> {
1417        if let Some(api_key) = &self.api_key {
1418            videos::list_video_models_with_client(self.http_client(), &self.base_url, api_key).await
1419        } else {
1420            Err(OpenRouterError::KeyNotConfigured)
1421        }
1422    }
1423
1424    /// Get the status of one video generation job.
1425    pub async fn get_video_generation(
1426        &self,
1427        job_id: &str,
1428    ) -> Result<videos::VideoGenerationResponse, OpenRouterError> {
1429        if let Some(api_key) = &self.api_key {
1430            videos::get_video_generation_with_client(
1431                self.http_client(),
1432                &self.base_url,
1433                api_key,
1434                job_id,
1435            )
1436            .await
1437        } else {
1438            Err(OpenRouterError::KeyNotConfigured)
1439        }
1440    }
1441
1442    /// Download the binary output for a completed video generation job.
1443    pub async fn get_video_content(
1444        &self,
1445        job_id: &str,
1446        index: Option<u32>,
1447    ) -> Result<Vec<u8>, OpenRouterError> {
1448        if let Some(api_key) = &self.api_key {
1449            videos::get_video_content_with_client(
1450                self.http_client(),
1451                &self.base_url,
1452                api_key,
1453                job_id,
1454                index,
1455            )
1456            .await
1457        } else {
1458            Err(OpenRouterError::KeyNotConfigured)
1459        }
1460    }
1461
1462    /// List files in the default or selected workspace.
1463    pub async fn list_files(
1464        &self,
1465        limit: Option<u32>,
1466        cursor: Option<&str>,
1467        workspace_id: Option<&str>,
1468    ) -> Result<files::FileListResponse, OpenRouterError> {
1469        if let Some(api_key) = &self.api_key {
1470            files::list_files_with_client(
1471                self.http_client(),
1472                &self.base_url,
1473                api_key,
1474                limit,
1475                cursor,
1476                workspace_id,
1477            )
1478            .await
1479        } else {
1480            Err(OpenRouterError::KeyNotConfigured)
1481        }
1482    }
1483
1484    /// Upload a file into the default or selected workspace.
1485    pub async fn upload_file(
1486        &self,
1487        request: &files::UploadFileRequest,
1488        workspace_id: Option<&str>,
1489    ) -> Result<files::FileMetadata, OpenRouterError> {
1490        if let Some(api_key) = &self.api_key {
1491            files::upload_file_with_client(
1492                self.http_client(),
1493                &self.base_url,
1494                api_key,
1495                request,
1496                workspace_id,
1497            )
1498            .await
1499        } else {
1500            Err(OpenRouterError::KeyNotConfigured)
1501        }
1502    }
1503
1504    /// Get metadata for one file.
1505    pub async fn get_file_metadata(
1506        &self,
1507        file_id: &str,
1508        workspace_id: Option<&str>,
1509    ) -> Result<files::FileMetadata, OpenRouterError> {
1510        if let Some(api_key) = &self.api_key {
1511            files::get_file_metadata_with_client(
1512                self.http_client(),
1513                &self.base_url,
1514                api_key,
1515                file_id,
1516                workspace_id,
1517            )
1518            .await
1519        } else {
1520            Err(OpenRouterError::KeyNotConfigured)
1521        }
1522    }
1523
1524    /// Download raw content for one file.
1525    pub async fn download_file_content(
1526        &self,
1527        file_id: &str,
1528        workspace_id: Option<&str>,
1529    ) -> Result<Vec<u8>, OpenRouterError> {
1530        if let Some(api_key) = &self.api_key {
1531            files::download_file_content_with_client(
1532                self.http_client(),
1533                &self.base_url,
1534                api_key,
1535                file_id,
1536                workspace_id,
1537            )
1538            .await
1539        } else {
1540            Err(OpenRouterError::KeyNotConfigured)
1541        }
1542    }
1543
1544    /// Delete one file.
1545    pub async fn delete_file(
1546        &self,
1547        file_id: &str,
1548        workspace_id: Option<&str>,
1549    ) -> Result<files::FileDeleteResponse, OpenRouterError> {
1550        if let Some(api_key) = &self.api_key {
1551            files::delete_file_with_client(
1552                self.http_client(),
1553                &self.base_url,
1554                api_key,
1555                file_id,
1556                workspace_id,
1557            )
1558            .await
1559        } else {
1560            Err(OpenRouterError::KeyNotConfigured)
1561        }
1562    }
1563
1564    /// List all available embeddings models.
1565    pub async fn list_embedding_models(&self) -> Result<Vec<models::Model>, OpenRouterError> {
1566        if let Some(api_key) = &self.api_key {
1567            embeddings::list_embedding_models_with_client(
1568                self.http_client(),
1569                &self.base_url,
1570                api_key,
1571            )
1572            .await
1573        } else {
1574            Err(OpenRouterError::KeyNotConfigured)
1575        }
1576    }
1577
1578    /// Creates and hydrates a Coinbase Commerce charge for cryptocurrency payments.
1579    ///
1580    /// # Arguments
1581    ///
1582    /// * `request` - The request data built using CoinbaseChargeRequest::builder().
1583    ///
1584    /// # Returns
1585    ///
1586    /// * `Result<credits::CoinbaseChargeData, OpenRouterError>` - The response data containing the charge details.
1587    ///
1588    /// # Example
1589    ///
1590    /// ```no_run
1591    /// # use openrouter_rs::{OpenRouterClient, api::credits};
1592    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
1593    /// let client = OpenRouterClient::builder().api_key("your_api_key").build()?;
1594    /// let request = credits::CoinbaseChargeRequest::builder()
1595    ///     .amount(100.0)
1596    ///     .sender("sender_address")
1597    ///     .chain_id(1)
1598    ///     .build()?;
1599    /// let response = client.create_coinbase_charge(&request).await?;
1600    /// println!("{:?}", response);
1601    /// # Ok(())
1602    /// # }
1603    /// ```
1604    pub async fn create_coinbase_charge(
1605        &self,
1606        request: &credits::CoinbaseChargeRequest,
1607    ) -> Result<credits::CoinbaseChargeData, OpenRouterError> {
1608        if let Some(api_key) = &self.api_key {
1609            credits::create_coinbase_charge_with_client(
1610                self.http_client(),
1611                &self.base_url,
1612                api_key,
1613                request,
1614            )
1615            .await
1616        } else {
1617            Err(OpenRouterError::KeyNotConfigured)
1618        }
1619    }
1620
1621    /// Returns the total credits purchased and used for the authenticated user.
1622    ///
1623    /// # Returns
1624    ///
1625    /// * `Result<credits::CreditsData, OpenRouterError>` - The response data containing the total credits and usage.
1626    ///
1627    /// # Example
1628    ///
1629    /// ```no_run
1630    /// # use openrouter_rs::OpenRouterClient;
1631    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
1632    /// let client = OpenRouterClient::builder().api_key("your_api_key").build()?;
1633    /// let credits_data = client.get_credits().await?;
1634    /// println!("{:?}", credits_data);
1635    /// # Ok(())
1636    /// # }
1637    /// ```
1638    pub async fn get_credits(&self) -> Result<credits::CreditsData, OpenRouterError> {
1639        if let Some(api_key) = &self.api_key {
1640            credits::get_credits_with_client(self.http_client(), &self.base_url, api_key).await
1641        } else {
1642            Err(OpenRouterError::KeyNotConfigured)
1643        }
1644    }
1645
1646    /// Returns metadata about a specific generation request.
1647    ///
1648    /// # Arguments
1649    ///
1650    /// * `id` - The generation identifier returned by OpenRouter.
1651    ///
1652    /// # Returns
1653    ///
1654    /// * `Result<generation::GenerationData, OpenRouterError>` - The metadata of the generation request or an error.
1655    ///
1656    /// # Example
1657    ///
1658    /// ```no_run
1659    /// # use openrouter_rs::OpenRouterClient;
1660    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
1661    /// let client = OpenRouterClient::builder().api_key("your_api_key").build()?;
1662    /// let generation_data = client.get_generation("generation_id").await?;
1663    /// println!("{:?}", generation_data);
1664    /// # Ok(())
1665    /// # }
1666    /// ```
1667    pub async fn get_generation(
1668        &self,
1669        id: impl Into<String>,
1670    ) -> Result<generation::GenerationData, OpenRouterError> {
1671        if let Some(api_key) = &self.api_key {
1672            generation::get_generation_with_client(self.http_client(), &self.base_url, api_key, id)
1673                .await
1674        } else {
1675            Err(OpenRouterError::KeyNotConfigured)
1676        }
1677    }
1678
1679    /// Returns the stored prompt/input and completion/output content for a specific generation.
1680    ///
1681    /// # Arguments
1682    ///
1683    /// * `id` - The generation identifier returned by OpenRouter.
1684    ///
1685    /// # Example
1686    ///
1687    /// ```no_run
1688    /// # use openrouter_rs::OpenRouterClient;
1689    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
1690    /// let client = OpenRouterClient::builder().api_key("your_api_key").build()?;
1691    /// let generation_content = client.get_generation_content("generation_id").await?;
1692    /// println!("{:?}", generation_content.output);
1693    /// # Ok(())
1694    /// # }
1695    /// ```
1696    pub async fn get_generation_content(
1697        &self,
1698        id: impl Into<String>,
1699    ) -> Result<generation::GenerationContentData, OpenRouterError> {
1700        if let Some(api_key) = &self.api_key {
1701            generation::get_generation_content_with_client(
1702                self.http_client(),
1703                &self.base_url,
1704                api_key,
1705                id,
1706            )
1707            .await
1708        } else {
1709            Err(OpenRouterError::KeyNotConfigured)
1710        }
1711    }
1712
1713    /// Returns a list of models available through the API.
1714    ///
1715    /// # Returns
1716    ///
1717    /// * `Result<Vec<models::Model>, OpenRouterError>` - A list of models or an error.
1718    ///
1719    /// # Example
1720    ///
1721    /// ```no_run
1722    /// # use openrouter_rs::OpenRouterClient;
1723    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
1724    /// let client = OpenRouterClient::builder().api_key("your_api_key").build()?;
1725    /// let models = client.list_models().await?;
1726    /// println!("{:?}", models);
1727    /// # Ok(())
1728    /// # }
1729    /// ```
1730    pub async fn list_models(&self) -> Result<Vec<models::Model>, OpenRouterError> {
1731        if let Some(api_key) = &self.api_key {
1732            models::list_models_with_client(self.http_client(), &self.base_url, api_key, None, None)
1733                .await
1734        } else {
1735            Err(OpenRouterError::KeyNotConfigured)
1736        }
1737    }
1738
1739    /// Returns a list of models using the extended OpenAPI filter surface.
1740    pub async fn list_models_filtered(
1741        &self,
1742        params: Option<&models::ListModelsParams>,
1743    ) -> Result<Vec<models::Model>, OpenRouterError> {
1744        if let Some(api_key) = &self.api_key {
1745            models::list_models_with_params_and_client(
1746                self.http_client(),
1747                &self.base_url,
1748                api_key,
1749                params,
1750            )
1751            .await
1752        } else {
1753            Err(OpenRouterError::KeyNotConfigured)
1754        }
1755    }
1756
1757    /// Returns metadata about one model.
1758    pub async fn get_model(
1759        &self,
1760        author: &str,
1761        slug: &str,
1762    ) -> Result<models::Model, OpenRouterError> {
1763        if let Some(api_key) = &self.api_key {
1764            models::get_model_with_client(self.http_client(), &self.base_url, api_key, author, slug)
1765                .await
1766        } else {
1767            Err(OpenRouterError::KeyNotConfigured)
1768        }
1769    }
1770
1771    /// Returns a list of models available through the API by category.
1772    ///
1773    /// # Arguments
1774    ///
1775    /// * `category` - The category of the models.
1776    ///
1777    /// # Returns
1778    ///
1779    /// * `Result<Vec<models::Model>, OpenRouterError>` - A list of models or an error.
1780    ///
1781    /// # Example
1782    ///
1783    /// ```no_run
1784    /// # use openrouter_rs::{OpenRouterClient, types::ModelCategory};
1785    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
1786    /// let client = OpenRouterClient::builder().api_key("your_api_key").build()?;
1787    /// let models = client.list_models_by_category(ModelCategory::Programming).await?;
1788    /// println!("{:?}", models);
1789    /// # Ok(())
1790    /// # }
1791    /// ```
1792    pub async fn list_models_by_category(
1793        &self,
1794        category: ModelCategory,
1795    ) -> Result<Vec<models::Model>, OpenRouterError> {
1796        if let Some(api_key) = &self.api_key {
1797            models::list_models_with_client(
1798                self.http_client(),
1799                &self.base_url,
1800                api_key,
1801                Some(category),
1802                None,
1803            )
1804            .await
1805        } else {
1806            Err(OpenRouterError::KeyNotConfigured)
1807        }
1808    }
1809
1810    /// Returns a list of models available for the specified supported parameters.
1811    ///
1812    /// # Arguments
1813    ///
1814    /// * `supported_parameters` - The supported parameters for the models.
1815    ///
1816    /// # Returns
1817    ///
1818    /// * `Result<Vec<models::Model>, OpenRouterError>` - A list of models or an error.
1819    ///
1820    /// # Example
1821    ///
1822    /// ```no_run
1823    /// # use openrouter_rs::{OpenRouterClient, types::SupportedParameters};
1824    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
1825    /// let client = OpenRouterClient::builder().api_key("your_api_key").build()?;
1826    /// let models = client.list_models_by_parameters(SupportedParameters::Tools).await?;
1827    /// println!("{:?}", models);
1828    /// # Ok(())
1829    /// # }
1830    /// ```
1831    pub async fn list_models_by_parameters(
1832        &self,
1833        supported_parameters: SupportedParameters,
1834    ) -> Result<Vec<models::Model>, OpenRouterError> {
1835        if let Some(api_key) = &self.api_key {
1836            models::list_models_with_client(
1837                self.http_client(),
1838                &self.base_url,
1839                api_key,
1840                None,
1841                Some(supported_parameters),
1842            )
1843            .await
1844        } else {
1845            Err(OpenRouterError::KeyNotConfigured)
1846        }
1847    }
1848
1849    /// Returns details about the endpoints for a specific model.
1850    ///
1851    /// # Arguments
1852    ///
1853    /// * `author` - The author of the model.
1854    /// * `slug` - The slug identifier for the model.
1855    ///
1856    /// # Returns
1857    ///
1858    /// * `Result<models::EndpointData, OpenRouterError>` - The endpoint data or an error.
1859    ///
1860    /// # Example
1861    ///
1862    /// ```no_run
1863    /// # use openrouter_rs::OpenRouterClient;
1864    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
1865    /// let client = OpenRouterClient::builder().api_key("your_api_key").build()?;
1866    /// let endpoint_data = client.list_model_endpoints("author_name", "model_slug").await?;
1867    /// println!("{:?}", endpoint_data);
1868    /// # Ok(())
1869    /// # }
1870    /// ```
1871    pub async fn list_model_endpoints(
1872        &self,
1873        author: &str,
1874        slug: &str,
1875    ) -> Result<models::EndpointData, OpenRouterError> {
1876        if let Some(api_key) = &self.api_key {
1877            models::list_model_endpoints_with_client(
1878                self.http_client(),
1879                &self.base_url,
1880                api_key,
1881                author,
1882                slug,
1883            )
1884            .await
1885        } else {
1886            Err(OpenRouterError::KeyNotConfigured)
1887        }
1888    }
1889
1890    /// List all providers.
1891    ///
1892    /// This endpoint is public, but this SDK method still requires `api_key`
1893    /// for consistency with other client operations.
1894    pub async fn list_providers(&self) -> Result<Vec<discovery::Provider>, OpenRouterError> {
1895        if let Some(api_key) = &self.api_key {
1896            discovery::list_providers_with_client(self.http_client(), &self.base_url, api_key).await
1897        } else {
1898            Err(OpenRouterError::KeyNotConfigured)
1899        }
1900    }
1901
1902    /// List models filtered by user provider preferences, privacy settings, and guardrails.
1903    ///
1904    /// Equivalent to `GET /models/user`.
1905    pub async fn list_models_for_user(&self) -> Result<Vec<discovery::UserModel>, OpenRouterError> {
1906        if let Some(api_key) = &self.api_key {
1907            discovery::list_models_for_user_with_client(self.http_client(), &self.base_url, api_key)
1908                .await
1909        } else {
1910            Err(OpenRouterError::KeyNotConfigured)
1911        }
1912    }
1913
1914    /// Get the total number of available models.
1915    ///
1916    /// Equivalent to `GET /models/count`.
1917    pub async fn count_models(&self) -> Result<discovery::ModelsCountData, OpenRouterError> {
1918        if let Some(api_key) = &self.api_key {
1919            discovery::count_models_with_client(self.http_client(), &self.base_url, api_key).await
1920        } else {
1921            Err(OpenRouterError::KeyNotConfigured)
1922        }
1923    }
1924
1925    /// Return daily token totals for top public models.
1926    ///
1927    /// Equivalent to `GET /datasets/rankings-daily`.
1928    pub async fn get_rankings_daily(
1929        &self,
1930        start_date: Option<&str>,
1931        end_date: Option<&str>,
1932    ) -> Result<discovery::RankingsDailyResponse, OpenRouterError> {
1933        if let Some(api_key) = &self.api_key {
1934            discovery::get_rankings_daily_with_client(
1935                self.http_client(),
1936                &self.base_url,
1937                api_key,
1938                start_date,
1939                end_date,
1940            )
1941            .await
1942        } else {
1943            Err(OpenRouterError::KeyNotConfigured)
1944        }
1945    }
1946
1947    /// Return ranked applications over a date window.
1948    pub async fn get_app_rankings(
1949        &self,
1950        params: Option<&discovery::AppRankingsParams>,
1951    ) -> Result<discovery::AppRankingsResponse, OpenRouterError> {
1952        if let Some(api_key) = &self.api_key {
1953            discovery::get_app_rankings_with_client(
1954                self.http_client(),
1955                &self.base_url,
1956                api_key,
1957                params,
1958            )
1959            .await
1960        } else {
1961            Err(OpenRouterError::KeyNotConfigured)
1962        }
1963    }
1964
1965    /// Return task classification market-share data.
1966    ///
1967    /// Equivalent to `GET /classifications/task`.
1968    pub async fn get_task_classifications(
1969        &self,
1970        window: Option<&str>,
1971    ) -> Result<discovery::TaskClassificationsResponse, OpenRouterError> {
1972        if let Some(api_key) = &self.api_key {
1973            discovery::get_task_classifications_with_client(
1974                self.http_client(),
1975                &self.base_url,
1976                api_key,
1977                window,
1978            )
1979            .await
1980        } else {
1981            Err(OpenRouterError::KeyNotConfigured)
1982        }
1983    }
1984
1985    /// Return benchmark rows from a selected source.
1986    ///
1987    /// Equivalent to `GET /benchmarks`.
1988    pub async fn get_benchmarks(
1989        &self,
1990        params: &discovery::UnifiedBenchmarksParams,
1991    ) -> Result<discovery::UnifiedBenchmarksResponse, OpenRouterError> {
1992        if let Some(api_key) = &self.api_key {
1993            discovery::get_benchmarks_with_client(
1994                self.http_client(),
1995                &self.base_url,
1996                api_key,
1997                params,
1998            )
1999            .await
2000        } else {
2001            Err(OpenRouterError::KeyNotConfigured)
2002        }
2003    }
2004
2005    /// Return Artificial Analysis benchmark rows.
2006    #[deprecated(note = "use get_benchmarks with source `artificial-analysis`")]
2007    #[allow(deprecated)]
2008    pub async fn get_benchmarks_artificial_analysis(
2009        &self,
2010        max_results: Option<u32>,
2011    ) -> Result<discovery::BenchmarksAAResponse, OpenRouterError> {
2012        if let Some(api_key) = &self.api_key {
2013            discovery::get_benchmarks_artificial_analysis_with_client(
2014                self.http_client(),
2015                &self.base_url,
2016                api_key,
2017                max_results,
2018            )
2019            .await
2020        } else {
2021            Err(OpenRouterError::KeyNotConfigured)
2022        }
2023    }
2024
2025    /// Return Design Arena benchmark rows.
2026    #[deprecated(note = "use get_benchmarks with source `design-arena`")]
2027    #[allow(deprecated)]
2028    pub async fn get_benchmarks_design_arena(
2029        &self,
2030        arena: Option<&str>,
2031        category: Option<&str>,
2032        max_results: Option<u32>,
2033    ) -> Result<discovery::BenchmarksDAResponse, OpenRouterError> {
2034        if let Some(api_key) = &self.api_key {
2035            discovery::get_benchmarks_design_arena_with_client(
2036                self.http_client(),
2037                &self.base_url,
2038                api_key,
2039                arena,
2040                category,
2041                max_results,
2042            )
2043            .await
2044        } else {
2045            Err(OpenRouterError::KeyNotConfigured)
2046        }
2047    }
2048
2049    /// Preview ZDR-compatible endpoints.
2050    ///
2051    /// Equivalent to `GET /endpoints/zdr`.
2052    pub async fn list_zdr_endpoints(
2053        &self,
2054    ) -> Result<Vec<discovery::PublicEndpoint>, OpenRouterError> {
2055        if let Some(api_key) = &self.api_key {
2056            discovery::list_zdr_endpoints_with_client(self.http_client(), &self.base_url, api_key)
2057                .await
2058        } else {
2059            Err(OpenRouterError::KeyNotConfigured)
2060        }
2061    }
2062
2063    /// Get activity grouped by endpoint for the last 30 UTC days.
2064    ///
2065    /// Equivalent to `GET /activity`.
2066    ///
2067    /// Requires a management API key. In this SDK, configure that via
2068    /// `OpenRouterClientBuilder::management_key(...)`.
2069    ///
2070    /// `date` is optional and should be `YYYY-MM-DD`.
2071    pub async fn get_activity(
2072        &self,
2073        date: Option<&str>,
2074    ) -> Result<Vec<discovery::ActivityItem>, OpenRouterError> {
2075        if let Some(management_key) = &self.management_key {
2076            discovery::get_activity_with_client(
2077                self.http_client(),
2078                &self.base_url,
2079                management_key,
2080                date,
2081            )
2082            .await
2083        } else {
2084            Err(OpenRouterError::KeyNotConfigured)
2085        }
2086    }
2087
2088    /// Get analytics metadata (`GET /analytics/meta`).
2089    pub async fn get_analytics_meta(&self) -> Result<analytics::AnalyticsMeta, OpenRouterError> {
2090        if let Some(management_key) = &self.management_key {
2091            analytics::get_analytics_meta_with_client(
2092                self.http_client(),
2093                &self.base_url,
2094                management_key,
2095            )
2096            .await
2097        } else {
2098            Err(OpenRouterError::KeyNotConfigured)
2099        }
2100    }
2101
2102    /// Query analytics (`POST /analytics/query`).
2103    pub async fn query_analytics(
2104        &self,
2105        request: &analytics::AnalyticsQueryRequest,
2106    ) -> Result<analytics::AnalyticsQueryResponse, OpenRouterError> {
2107        if let Some(management_key) = &self.management_key {
2108            analytics::query_analytics_with_client(
2109                self.http_client(),
2110                &self.base_url,
2111                management_key,
2112                request,
2113            )
2114            .await
2115        } else {
2116            Err(OpenRouterError::KeyNotConfigured)
2117        }
2118    }
2119
2120    /// List BYOK provider credentials (`GET /byok`). Requires a management key.
2121    pub async fn list_byok_keys(
2122        &self,
2123        pagination: Option<PaginationOptions>,
2124        workspace_id: Option<&str>,
2125        provider: Option<&str>,
2126    ) -> Result<byok::ByokKeyListResponse, OpenRouterError> {
2127        if let Some(management_key) = &self.management_key {
2128            byok::list_byok_keys_with_client(
2129                self.http_client(),
2130                &self.base_url,
2131                management_key,
2132                pagination,
2133                workspace_id,
2134                provider,
2135            )
2136            .await
2137        } else {
2138            Err(OpenRouterError::KeyNotConfigured)
2139        }
2140    }
2141
2142    /// Create a BYOK provider credential (`POST /byok`). Requires a management key.
2143    pub async fn create_byok_key(
2144        &self,
2145        request: &byok::CreateByokKeyRequest,
2146    ) -> Result<byok::ByokKey, OpenRouterError> {
2147        if let Some(management_key) = &self.management_key {
2148            byok::create_byok_key_with_client(
2149                self.http_client(),
2150                &self.base_url,
2151                management_key,
2152                request,
2153            )
2154            .await
2155        } else {
2156            Err(OpenRouterError::KeyNotConfigured)
2157        }
2158    }
2159
2160    /// Get a BYOK provider credential (`GET /byok/{id}`). Requires a management key.
2161    pub async fn get_byok_key(&self, id: &str) -> Result<byok::ByokKey, OpenRouterError> {
2162        if let Some(management_key) = &self.management_key {
2163            byok::get_byok_key_with_client(self.http_client(), &self.base_url, management_key, id)
2164                .await
2165        } else {
2166            Err(OpenRouterError::KeyNotConfigured)
2167        }
2168    }
2169
2170    /// Update a BYOK provider credential (`PATCH /byok/{id}`). Requires a management key.
2171    pub async fn update_byok_key(
2172        &self,
2173        id: &str,
2174        request: &byok::UpdateByokKeyRequest,
2175    ) -> Result<byok::ByokKey, OpenRouterError> {
2176        if let Some(management_key) = &self.management_key {
2177            byok::update_byok_key_with_client(
2178                self.http_client(),
2179                &self.base_url,
2180                management_key,
2181                id,
2182                request,
2183            )
2184            .await
2185        } else {
2186            Err(OpenRouterError::KeyNotConfigured)
2187        }
2188    }
2189
2190    /// Delete a BYOK provider credential (`DELETE /byok/{id}`). Requires a management key.
2191    pub async fn delete_byok_key(&self, id: &str) -> Result<bool, OpenRouterError> {
2192        if let Some(management_key) = &self.management_key {
2193            byok::delete_byok_key_with_client(
2194                self.http_client(),
2195                &self.base_url,
2196                management_key,
2197                id,
2198            )
2199            .await
2200        } else {
2201            Err(OpenRouterError::KeyNotConfigured)
2202        }
2203    }
2204
2205    /// List observability destinations (`GET /observability/destinations`).
2206    pub async fn list_observability_destinations(
2207        &self,
2208        pagination: Option<PaginationOptions>,
2209        workspace_id: Option<&str>,
2210    ) -> Result<observability::ObservabilityDestinationListResponse, OpenRouterError> {
2211        if let Some(management_key) = &self.management_key {
2212            observability::list_observability_destinations_with_client(
2213                self.http_client(),
2214                &self.base_url,
2215                management_key,
2216                pagination,
2217                workspace_id,
2218            )
2219            .await
2220        } else {
2221            Err(OpenRouterError::KeyNotConfigured)
2222        }
2223    }
2224
2225    /// Create an observability destination (`POST /observability/destinations`).
2226    pub async fn create_observability_destination(
2227        &self,
2228        request: &observability::CreateObservabilityDestinationRequest,
2229    ) -> Result<observability::ObservabilityDestination, OpenRouterError> {
2230        if let Some(management_key) = &self.management_key {
2231            observability::create_observability_destination_with_client(
2232                self.http_client(),
2233                &self.base_url,
2234                management_key,
2235                request,
2236            )
2237            .await
2238        } else {
2239            Err(OpenRouterError::KeyNotConfigured)
2240        }
2241    }
2242
2243    /// Get an observability destination (`GET /observability/destinations/{id}`).
2244    pub async fn get_observability_destination(
2245        &self,
2246        id: &str,
2247    ) -> Result<observability::ObservabilityDestination, OpenRouterError> {
2248        if let Some(management_key) = &self.management_key {
2249            observability::get_observability_destination_with_client(
2250                self.http_client(),
2251                &self.base_url,
2252                management_key,
2253                id,
2254            )
2255            .await
2256        } else {
2257            Err(OpenRouterError::KeyNotConfigured)
2258        }
2259    }
2260
2261    /// Update an observability destination (`PATCH /observability/destinations/{id}`).
2262    pub async fn update_observability_destination(
2263        &self,
2264        id: &str,
2265        request: &observability::UpdateObservabilityDestinationRequest,
2266    ) -> Result<observability::ObservabilityDestination, OpenRouterError> {
2267        if let Some(management_key) = &self.management_key {
2268            observability::update_observability_destination_with_client(
2269                self.http_client(),
2270                &self.base_url,
2271                management_key,
2272                id,
2273                request,
2274            )
2275            .await
2276        } else {
2277            Err(OpenRouterError::KeyNotConfigured)
2278        }
2279    }
2280
2281    /// Delete an observability destination (`DELETE /observability/destinations/{id}`).
2282    pub async fn delete_observability_destination(
2283        &self,
2284        id: &str,
2285    ) -> Result<bool, OpenRouterError> {
2286        if let Some(management_key) = &self.management_key {
2287            observability::delete_observability_destination_with_client(
2288                self.http_client(),
2289                &self.base_url,
2290                management_key,
2291                id,
2292            )
2293            .await
2294        } else {
2295            Err(OpenRouterError::KeyNotConfigured)
2296        }
2297    }
2298
2299    /// List organization members for the configured management key.
2300    pub async fn list_organization_members(
2301        &self,
2302        pagination: Option<PaginationOptions>,
2303    ) -> Result<organization::OrganizationMembersResponse, OpenRouterError> {
2304        if let Some(management_key) = &self.management_key {
2305            organization::list_organization_members_with_client(
2306                self.http_client(),
2307                &self.base_url,
2308                management_key,
2309                pagination,
2310            )
2311            .await
2312        } else {
2313            Err(OpenRouterError::KeyNotConfigured)
2314        }
2315    }
2316
2317    /// List workspaces for the configured management key.
2318    pub async fn list_workspaces(
2319        &self,
2320        pagination: Option<PaginationOptions>,
2321    ) -> Result<workspaces::WorkspaceListResponse, OpenRouterError> {
2322        if let Some(management_key) = &self.management_key {
2323            workspaces::list_workspaces_with_client(
2324                self.http_client(),
2325                &self.base_url,
2326                management_key,
2327                pagination,
2328            )
2329            .await
2330        } else {
2331            Err(OpenRouterError::KeyNotConfigured)
2332        }
2333    }
2334
2335    /// Create a workspace (`POST /workspaces`).
2336    pub async fn create_workspace(
2337        &self,
2338        request: &workspaces::CreateWorkspaceRequest,
2339    ) -> Result<workspaces::Workspace, OpenRouterError> {
2340        if let Some(management_key) = &self.management_key {
2341            workspaces::create_workspace_with_client(
2342                self.http_client(),
2343                &self.base_url,
2344                management_key,
2345                request,
2346            )
2347            .await
2348        } else {
2349            Err(OpenRouterError::KeyNotConfigured)
2350        }
2351    }
2352
2353    /// Get a workspace (`GET /workspaces/{id}`).
2354    pub async fn get_workspace(&self, id: &str) -> Result<workspaces::Workspace, OpenRouterError> {
2355        if let Some(management_key) = &self.management_key {
2356            workspaces::get_workspace_with_client(
2357                self.http_client(),
2358                &self.base_url,
2359                management_key,
2360                id,
2361            )
2362            .await
2363        } else {
2364            Err(OpenRouterError::KeyNotConfigured)
2365        }
2366    }
2367
2368    /// Update a workspace (`PATCH /workspaces/{id}`).
2369    pub async fn update_workspace(
2370        &self,
2371        id: &str,
2372        request: &workspaces::UpdateWorkspaceRequest,
2373    ) -> Result<workspaces::Workspace, OpenRouterError> {
2374        if let Some(management_key) = &self.management_key {
2375            workspaces::update_workspace_with_client(
2376                self.http_client(),
2377                &self.base_url,
2378                management_key,
2379                id,
2380                request,
2381            )
2382            .await
2383        } else {
2384            Err(OpenRouterError::KeyNotConfigured)
2385        }
2386    }
2387
2388    /// Update a workspace and clear I/O logging API key filters (`PATCH /workspaces/{id}`).
2389    pub async fn update_workspace_with_cleared_io_logging_api_key_ids(
2390        &self,
2391        id: &str,
2392        request: &workspaces::UpdateWorkspaceRequest,
2393    ) -> Result<workspaces::Workspace, OpenRouterError> {
2394        if let Some(management_key) = &self.management_key {
2395            workspaces::update_workspace_with_cleared_io_logging_api_key_ids_with_client(
2396                self.http_client(),
2397                &self.base_url,
2398                management_key,
2399                id,
2400                request,
2401            )
2402            .await
2403        } else {
2404            Err(OpenRouterError::KeyNotConfigured)
2405        }
2406    }
2407
2408    /// Delete a workspace (`DELETE /workspaces/{id}`).
2409    pub async fn delete_workspace(&self, id: &str) -> Result<bool, OpenRouterError> {
2410        if let Some(management_key) = &self.management_key {
2411            workspaces::delete_workspace_with_client(
2412                self.http_client(),
2413                &self.base_url,
2414                management_key,
2415                id,
2416            )
2417            .await
2418        } else {
2419            Err(OpenRouterError::KeyNotConfigured)
2420        }
2421    }
2422
2423    /// List budgets configured for a workspace (`GET /workspaces/{id}/budgets`).
2424    pub async fn list_workspace_budgets(
2425        &self,
2426        id: &str,
2427    ) -> Result<workspaces::ListWorkspaceBudgetsResponse, OpenRouterError> {
2428        if let Some(management_key) = &self.management_key {
2429            workspaces::list_workspace_budgets_with_client(
2430                self.http_client(),
2431                &self.base_url,
2432                management_key,
2433                id,
2434            )
2435            .await
2436        } else {
2437            Err(OpenRouterError::KeyNotConfigured)
2438        }
2439    }
2440
2441    /// Create or update a workspace budget (`PUT /workspaces/{id}/budgets/{interval}`).
2442    pub async fn upsert_workspace_budget(
2443        &self,
2444        id: &str,
2445        interval: &str,
2446        request: &workspaces::UpsertWorkspaceBudgetRequest,
2447    ) -> Result<workspaces::WorkspaceBudget, OpenRouterError> {
2448        if let Some(management_key) = &self.management_key {
2449            workspaces::upsert_workspace_budget_with_client(
2450                self.http_client(),
2451                &self.base_url,
2452                management_key,
2453                id,
2454                interval,
2455                request,
2456            )
2457            .await
2458        } else {
2459            Err(OpenRouterError::KeyNotConfigured)
2460        }
2461    }
2462
2463    /// Delete a workspace budget (`DELETE /workspaces/{id}/budgets/{interval}`).
2464    pub async fn delete_workspace_budget(
2465        &self,
2466        id: &str,
2467        interval: &str,
2468    ) -> Result<bool, OpenRouterError> {
2469        if let Some(management_key) = &self.management_key {
2470            workspaces::delete_workspace_budget_with_client(
2471                self.http_client(),
2472                &self.base_url,
2473                management_key,
2474                id,
2475                interval,
2476            )
2477            .await
2478        } else {
2479            Err(OpenRouterError::KeyNotConfigured)
2480        }
2481    }
2482
2483    /// Add multiple organization members to a workspace (`POST /workspaces/{id}/members/add`).
2484    pub async fn add_workspace_members(
2485        &self,
2486        id: &str,
2487        request: &workspaces::WorkspaceMembersRequest,
2488    ) -> Result<workspaces::WorkspaceMembersAddResponse, OpenRouterError> {
2489        if let Some(management_key) = &self.management_key {
2490            workspaces::add_workspace_members_with_client(
2491                self.http_client(),
2492                &self.base_url,
2493                management_key,
2494                id,
2495                request,
2496            )
2497            .await
2498        } else {
2499            Err(OpenRouterError::KeyNotConfigured)
2500        }
2501    }
2502
2503    /// Remove multiple organization members from a workspace (`POST /workspaces/{id}/members/remove`).
2504    pub async fn remove_workspace_members(
2505        &self,
2506        id: &str,
2507        request: &workspaces::WorkspaceMembersRequest,
2508    ) -> Result<workspaces::WorkspaceMembersRemoveResponse, OpenRouterError> {
2509        if let Some(management_key) = &self.management_key {
2510            workspaces::remove_workspace_members_with_client(
2511                self.http_client(),
2512                &self.base_url,
2513                management_key,
2514                id,
2515                request,
2516            )
2517            .await
2518        } else {
2519            Err(OpenRouterError::KeyNotConfigured)
2520        }
2521    }
2522}
2523
2524/// Domain client for chat completions.
2525#[derive(Debug, Clone, Copy)]
2526pub struct ChatClient<'a> {
2527    client: &'a OpenRouterClient,
2528}
2529
2530impl<'a> ChatClient<'a> {
2531    /// Create a chat completion (`POST /chat/completions`).
2532    pub async fn create(
2533        &self,
2534        request: &chat::ChatCompletionRequest,
2535    ) -> Result<CompletionsResponse, OpenRouterError> {
2536        self.client.send_chat_completion(request).await
2537    }
2538
2539    /// Stream chat completion chunks.
2540    pub async fn stream(
2541        &self,
2542        request: &chat::ChatCompletionRequest,
2543    ) -> Result<BoxStream<'static, Result<CompletionsResponse, OpenRouterError>>, OpenRouterError>
2544    {
2545        self.client.stream_chat_completion(request).await
2546    }
2547
2548    /// Stream chat completion chunks with tool-call-aware aggregation.
2549    pub async fn stream_tool_aware(
2550        &self,
2551        request: &chat::ChatCompletionRequest,
2552    ) -> Result<ToolAwareStream, OpenRouterError> {
2553        self.client.stream_chat_completion_tool_aware(request).await
2554    }
2555
2556    /// Stream chat events using the unified stream abstraction.
2557    pub async fn stream_unified(
2558        &self,
2559        request: &chat::ChatCompletionRequest,
2560    ) -> Result<UnifiedStream, OpenRouterError> {
2561        self.client.stream_chat_completion_unified(request).await
2562    }
2563}
2564
2565/// Domain client for OpenRouter Responses API.
2566#[derive(Debug, Clone, Copy)]
2567pub struct ResponsesClient<'a> {
2568    client: &'a OpenRouterClient,
2569}
2570
2571impl<'a> ResponsesClient<'a> {
2572    /// Create a response (`POST /responses`).
2573    pub async fn create(
2574        &self,
2575        request: &responses::ResponsesRequest,
2576    ) -> Result<responses::ResponsesResponse, OpenRouterError> {
2577        self.client.create_response(request).await
2578    }
2579
2580    /// Stream response events (`POST /responses`, `stream=true`).
2581    pub async fn stream(
2582        &self,
2583        request: &responses::ResponsesRequest,
2584    ) -> Result<
2585        BoxStream<'static, Result<responses::ResponsesStreamEvent, OpenRouterError>>,
2586        OpenRouterError,
2587    > {
2588        self.client.stream_response(request).await
2589    }
2590
2591    /// Stream response events using the unified stream abstraction.
2592    pub async fn stream_unified(
2593        &self,
2594        request: &responses::ResponsesRequest,
2595    ) -> Result<UnifiedStream, OpenRouterError> {
2596        self.client.stream_response_unified(request).await
2597    }
2598}
2599
2600/// Domain client for Anthropic-compatible Messages API.
2601#[derive(Debug, Clone, Copy)]
2602pub struct MessagesClient<'a> {
2603    client: &'a OpenRouterClient,
2604}
2605
2606impl<'a> MessagesClient<'a> {
2607    /// Create a non-streaming message (`POST /messages`).
2608    pub async fn create(
2609        &self,
2610        request: &messages::AnthropicMessagesRequest,
2611    ) -> Result<messages::AnthropicMessagesResponse, OpenRouterError> {
2612        self.client.create_message(request).await
2613    }
2614
2615    /// Stream SSE events from `/messages`.
2616    pub async fn stream(
2617        &self,
2618        request: &messages::AnthropicMessagesRequest,
2619    ) -> Result<
2620        BoxStream<'static, Result<messages::AnthropicMessagesSseEvent, OpenRouterError>>,
2621        OpenRouterError,
2622    > {
2623        self.client.stream_messages(request).await
2624    }
2625
2626    /// Stream messages events using the unified stream abstraction.
2627    pub async fn stream_unified(
2628        &self,
2629        request: &messages::AnthropicMessagesRequest,
2630    ) -> Result<UnifiedStream, OpenRouterError> {
2631        self.client.stream_messages_unified(request).await
2632    }
2633}
2634
2635/// Domain client for rerank endpoints.
2636#[derive(Debug, Clone, Copy)]
2637pub struct RerankClient<'a> {
2638    client: &'a OpenRouterClient,
2639}
2640
2641impl<'a> RerankClient<'a> {
2642    /// Create a rerank result set (`POST /rerank`).
2643    pub async fn create(
2644        &self,
2645        request: &rerank::RerankRequest,
2646    ) -> Result<rerank::RerankResponse, OpenRouterError> {
2647        self.client.create_rerank(request).await
2648    }
2649}
2650
2651/// Domain client for audio endpoints.
2652#[derive(Debug, Clone, Copy)]
2653pub struct AudioClient<'a> {
2654    client: &'a OpenRouterClient,
2655}
2656
2657impl<'a> AudioClient<'a> {
2658    /// Domain client for speech generation operations.
2659    pub fn speech(&self) -> SpeechClient<'a> {
2660        SpeechClient {
2661            client: self.client,
2662        }
2663    }
2664
2665    /// Domain client for audio transcription operations.
2666    pub fn transcriptions(&self) -> TranscriptionsClient<'a> {
2667        TranscriptionsClient {
2668            client: self.client,
2669        }
2670    }
2671}
2672
2673/// Domain client for audio speech endpoints.
2674#[derive(Debug, Clone, Copy)]
2675pub struct SpeechClient<'a> {
2676    client: &'a OpenRouterClient,
2677}
2678
2679impl<'a> SpeechClient<'a> {
2680    /// Create speech audio bytes (`POST /audio/speech`).
2681    pub async fn create(&self, request: &audio::SpeechRequest) -> Result<Vec<u8>, OpenRouterError> {
2682        self.client.create_speech(request).await
2683    }
2684}
2685
2686#[deprecated(note = "use SpeechClient")]
2687pub type TtsClient<'a> = SpeechClient<'a>;
2688
2689/// Domain client for audio transcription endpoints.
2690#[derive(Debug, Clone, Copy)]
2691pub struct TranscriptionsClient<'a> {
2692    client: &'a OpenRouterClient,
2693}
2694
2695impl<'a> TranscriptionsClient<'a> {
2696    /// Create an audio transcription (`POST /audio/transcriptions`).
2697    pub async fn create(
2698        &self,
2699        request: &audio::TranscriptionRequest,
2700    ) -> Result<audio::TranscriptionResponse, OpenRouterError> {
2701        self.client.create_transcription(request).await
2702    }
2703}
2704
2705/// Domain client for image generation endpoints.
2706#[derive(Debug, Clone, Copy)]
2707pub struct ImagesClient<'a> {
2708    client: &'a OpenRouterClient,
2709}
2710
2711impl<'a> ImagesClient<'a> {
2712    /// Submit an image generation request (`POST /images`).
2713    pub async fn create(
2714        &self,
2715        request: &images::ImageGenerationRequest,
2716    ) -> Result<images::ImageGenerationResponse, OpenRouterError> {
2717        self.client.create_image_generation(request).await
2718    }
2719
2720    /// Stream image generation events (`POST /images`, `stream=true`).
2721    pub async fn stream(
2722        &self,
2723        request: &images::ImageGenerationRequest,
2724    ) -> Result<
2725        BoxStream<'static, Result<images::ImageStreamingResponse, OpenRouterError>>,
2726        OpenRouterError,
2727    > {
2728        self.client.stream_image_generation(request).await
2729    }
2730
2731    /// List available image generation models (`GET /images/models`).
2732    pub async fn list_models(&self) -> Result<Vec<images::ImageModel>, OpenRouterError> {
2733        self.client.list_image_models().await
2734    }
2735
2736    /// List provider endpoints for one image generation model.
2737    pub async fn list_model_endpoints(
2738        &self,
2739        author: &str,
2740        slug: &str,
2741    ) -> Result<images::ImageModelEndpointsResponse, OpenRouterError> {
2742        self.client.list_image_model_endpoints(author, slug).await
2743    }
2744}
2745
2746/// Domain client for video generation endpoints.
2747#[derive(Debug, Clone, Copy)]
2748pub struct VideosClient<'a> {
2749    client: &'a OpenRouterClient,
2750}
2751
2752impl<'a> VideosClient<'a> {
2753    /// Submit a video generation request (`POST /videos`).
2754    pub async fn create(
2755        &self,
2756        request: &videos::VideoGenerationRequest,
2757    ) -> Result<videos::VideoGenerationResponse, OpenRouterError> {
2758        self.client.create_video_generation(request).await
2759    }
2760
2761    /// List available video generation models (`GET /videos/models`).
2762    pub async fn list_models(&self) -> Result<Vec<videos::VideoModel>, OpenRouterError> {
2763        self.client.list_video_models().await
2764    }
2765
2766    /// Poll a submitted video generation (`GET /videos/{jobId}`).
2767    pub async fn get_generation(
2768        &self,
2769        job_id: &str,
2770    ) -> Result<videos::VideoGenerationResponse, OpenRouterError> {
2771        self.client.get_video_generation(job_id).await
2772    }
2773
2774    /// Download video output bytes for a completed job (`GET /videos/{jobId}/content`).
2775    pub async fn get_content(
2776        &self,
2777        job_id: &str,
2778        index: Option<u32>,
2779    ) -> Result<Vec<u8>, OpenRouterError> {
2780        self.client.get_video_content(job_id, index).await
2781    }
2782}
2783
2784/// Domain client for file endpoints.
2785#[derive(Debug, Clone, Copy)]
2786pub struct FilesClient<'a> {
2787    client: &'a OpenRouterClient,
2788}
2789
2790impl<'a> FilesClient<'a> {
2791    /// List files (`GET /files`).
2792    pub async fn list(
2793        &self,
2794        limit: Option<u32>,
2795        cursor: Option<&str>,
2796        workspace_id: Option<&str>,
2797    ) -> Result<files::FileListResponse, OpenRouterError> {
2798        self.client.list_files(limit, cursor, workspace_id).await
2799    }
2800
2801    /// Upload a file (`POST /files`).
2802    pub async fn upload(
2803        &self,
2804        request: &files::UploadFileRequest,
2805        workspace_id: Option<&str>,
2806    ) -> Result<files::FileMetadata, OpenRouterError> {
2807        self.client.upload_file(request, workspace_id).await
2808    }
2809
2810    /// Get file metadata (`GET /files/{file_id}`).
2811    pub async fn get_metadata(
2812        &self,
2813        file_id: &str,
2814        workspace_id: Option<&str>,
2815    ) -> Result<files::FileMetadata, OpenRouterError> {
2816        self.client.get_file_metadata(file_id, workspace_id).await
2817    }
2818
2819    /// Download file content (`GET /files/{file_id}/content`).
2820    pub async fn download_content(
2821        &self,
2822        file_id: &str,
2823        workspace_id: Option<&str>,
2824    ) -> Result<Vec<u8>, OpenRouterError> {
2825        self.client
2826            .download_file_content(file_id, workspace_id)
2827            .await
2828    }
2829
2830    /// Delete a file (`DELETE /files/{file_id}`).
2831    pub async fn delete(
2832        &self,
2833        file_id: &str,
2834        workspace_id: Option<&str>,
2835    ) -> Result<files::FileDeleteResponse, OpenRouterError> {
2836        self.client.delete_file(file_id, workspace_id).await
2837    }
2838}
2839
2840/// Domain client for model/discovery/embedding endpoints.
2841#[derive(Debug, Clone, Copy)]
2842pub struct ModelsClient<'a> {
2843    client: &'a OpenRouterClient,
2844}
2845
2846impl<'a> ModelsClient<'a> {
2847    /// List all models (`GET /models`).
2848    pub async fn list(&self) -> Result<Vec<models::Model>, OpenRouterError> {
2849        self.client.list_models().await
2850    }
2851
2852    /// List models with the extended filter surface (`GET /models?...`).
2853    pub async fn list_filtered(
2854        &self,
2855        params: Option<&models::ListModelsParams>,
2856    ) -> Result<Vec<models::Model>, OpenRouterError> {
2857        self.client.list_models_filtered(params).await
2858    }
2859
2860    /// List models by category (`GET /models?category=...`).
2861    pub async fn list_by_category(
2862        &self,
2863        category: ModelCategory,
2864    ) -> Result<Vec<models::Model>, OpenRouterError> {
2865        self.client.list_models_by_category(category).await
2866    }
2867
2868    /// List models by supported parameter (`GET /models?supported_parameters=...`).
2869    pub async fn list_by_parameters(
2870        &self,
2871        supported_parameters: SupportedParameters,
2872    ) -> Result<Vec<models::Model>, OpenRouterError> {
2873        self.client
2874            .list_models_by_parameters(supported_parameters)
2875            .await
2876    }
2877
2878    /// List model endpoints (`GET /models/{author}/{slug}/endpoints`).
2879    pub async fn list_endpoints(
2880        &self,
2881        author: &str,
2882        slug: &str,
2883    ) -> Result<models::EndpointData, OpenRouterError> {
2884        self.client.list_model_endpoints(author, slug).await
2885    }
2886
2887    /// Get metadata about one model (`GET /model/{author}/{slug}`).
2888    pub async fn get(&self, author: &str, slug: &str) -> Result<models::Model, OpenRouterError> {
2889        self.client.get_model(author, slug).await
2890    }
2891
2892    /// List providers (`GET /providers`).
2893    pub async fn list_providers(&self) -> Result<Vec<discovery::Provider>, OpenRouterError> {
2894        self.client.list_providers().await
2895    }
2896
2897    /// List user-filtered models (`GET /models/user`).
2898    pub async fn list_user_models(&self) -> Result<Vec<discovery::UserModel>, OpenRouterError> {
2899        self.client.list_models_for_user().await
2900    }
2901
2902    /// Get available model count (`GET /models/count`).
2903    pub async fn get_model_count(&self) -> Result<discovery::ModelsCountData, OpenRouterError> {
2904        self.client.count_models().await
2905    }
2906
2907    /// Return daily token totals for top public models (`GET /datasets/rankings-daily`).
2908    pub async fn get_rankings_daily(
2909        &self,
2910        start_date: Option<&str>,
2911        end_date: Option<&str>,
2912    ) -> Result<discovery::RankingsDailyResponse, OpenRouterError> {
2913        self.client.get_rankings_daily(start_date, end_date).await
2914    }
2915
2916    /// Return ranked applications (`GET /datasets/app-rankings`).
2917    pub async fn get_app_rankings(
2918        &self,
2919        params: Option<&discovery::AppRankingsParams>,
2920    ) -> Result<discovery::AppRankingsResponse, OpenRouterError> {
2921        self.client.get_app_rankings(params).await
2922    }
2923
2924    /// Return task classification market-share data (`GET /classifications/task`).
2925    pub async fn get_task_classifications(
2926        &self,
2927        window: Option<&str>,
2928    ) -> Result<discovery::TaskClassificationsResponse, OpenRouterError> {
2929        self.client.get_task_classifications(window).await
2930    }
2931
2932    /// Return benchmark rows from a selected source (`GET /benchmarks`).
2933    pub async fn get_benchmarks(
2934        &self,
2935        params: &discovery::UnifiedBenchmarksParams,
2936    ) -> Result<discovery::UnifiedBenchmarksResponse, OpenRouterError> {
2937        self.client.get_benchmarks(params).await
2938    }
2939
2940    /// Return Artificial Analysis benchmark rows.
2941    #[deprecated(note = "use get_benchmarks with source `artificial-analysis`")]
2942    #[allow(deprecated)]
2943    pub async fn get_benchmarks_artificial_analysis(
2944        &self,
2945        max_results: Option<u32>,
2946    ) -> Result<discovery::BenchmarksAAResponse, OpenRouterError> {
2947        self.client
2948            .get_benchmarks_artificial_analysis(max_results)
2949            .await
2950    }
2951
2952    /// Return Design Arena benchmark rows.
2953    #[deprecated(note = "use get_benchmarks with source `design-arena`")]
2954    #[allow(deprecated)]
2955    pub async fn get_benchmarks_design_arena(
2956        &self,
2957        arena: Option<&str>,
2958        category: Option<&str>,
2959        max_results: Option<u32>,
2960    ) -> Result<discovery::BenchmarksDAResponse, OpenRouterError> {
2961        self.client
2962            .get_benchmarks_design_arena(arena, category, max_results)
2963            .await
2964    }
2965
2966    /// List ZDR-compatible endpoints (`GET /endpoints/zdr`).
2967    pub async fn list_zdr_endpoints(
2968        &self,
2969    ) -> Result<Vec<discovery::PublicEndpoint>, OpenRouterError> {
2970        self.client.list_zdr_endpoints().await
2971    }
2972
2973    /// Create an embedding (`POST /embeddings`).
2974    pub async fn create_embedding(
2975        &self,
2976        request: &embeddings::EmbeddingRequest,
2977    ) -> Result<embeddings::EmbeddingResponse, OpenRouterError> {
2978        self.client.create_embedding(request).await
2979    }
2980
2981    /// List embedding models (`GET /embeddings/models`).
2982    pub async fn list_embedding_models(&self) -> Result<Vec<models::Model>, OpenRouterError> {
2983        self.client.list_embedding_models().await
2984    }
2985}
2986
2987/// Domain client for management endpoints.
2988#[derive(Debug, Clone, Copy)]
2989pub struct ManagementClient<'a> {
2990    client: &'a OpenRouterClient,
2991}
2992
2993impl<'a> ManagementClient<'a> {
2994    /// Create a managed API key (`POST /keys`).
2995    pub async fn create_api_key(
2996        &self,
2997        name: &str,
2998        limit: Option<f64>,
2999    ) -> Result<api_keys::ApiKey, OpenRouterError> {
3000        self.client.create_api_key(name, limit).await
3001    }
3002
3003    /// Create a managed API key in a workspace (`POST /keys`).
3004    pub async fn create_api_key_in_workspace(
3005        &self,
3006        name: &str,
3007        limit: Option<f64>,
3008        workspace_id: Option<&str>,
3009    ) -> Result<api_keys::ApiKey, OpenRouterError> {
3010        self.client
3011            .create_api_key_in_workspace(name, limit, workspace_id)
3012            .await
3013    }
3014
3015    /// Get current key session info (`GET /key`).
3016    pub async fn get_current_api_key_info(
3017        &self,
3018    ) -> Result<api_keys::ApiKeyDetails, OpenRouterError> {
3019        self.client.get_current_api_key_info().await
3020    }
3021
3022    /// Create or update a preset from a chat-completions request body.
3023    pub async fn create_chat_completion_preset(
3024        &self,
3025        slug: &str,
3026        request: &chat::ChatCompletionRequest,
3027    ) -> Result<presets::PresetWithDesignatedVersion, OpenRouterError> {
3028        self.client
3029            .create_chat_completion_preset(slug, request)
3030            .await
3031    }
3032
3033    /// Create or update a preset from a Responses API request body.
3034    pub async fn create_response_preset(
3035        &self,
3036        slug: &str,
3037        request: &responses::ResponsesRequest,
3038    ) -> Result<presets::PresetWithDesignatedVersion, OpenRouterError> {
3039        self.client.create_response_preset(slug, request).await
3040    }
3041
3042    /// Create or update a preset from an Anthropic-compatible Messages request body.
3043    pub async fn create_message_preset(
3044        &self,
3045        slug: &str,
3046        request: &messages::AnthropicMessagesRequest,
3047    ) -> Result<presets::PresetWithDesignatedVersion, OpenRouterError> {
3048        self.client.create_message_preset(slug, request).await
3049    }
3050
3051    /// List presets (`GET /presets`).
3052    pub async fn list_presets(
3053        &self,
3054        pagination: Option<PaginationOptions>,
3055    ) -> Result<presets::ListPresetsResponse, OpenRouterError> {
3056        self.client.list_presets(pagination).await
3057    }
3058
3059    /// Get one preset (`GET /presets/{slug}`).
3060    pub async fn get_preset(
3061        &self,
3062        slug: &str,
3063    ) -> Result<presets::PresetWithDesignatedVersion, OpenRouterError> {
3064        self.client.get_preset(slug).await
3065    }
3066
3067    /// List preset versions (`GET /presets/{slug}/versions`).
3068    pub async fn list_preset_versions(
3069        &self,
3070        slug: &str,
3071        pagination: Option<PaginationOptions>,
3072    ) -> Result<presets::ListPresetVersionsResponse, OpenRouterError> {
3073        self.client.list_preset_versions(slug, pagination).await
3074    }
3075
3076    /// Get a preset version (`GET /presets/{slug}/versions/{version}`).
3077    pub async fn get_preset_version(
3078        &self,
3079        slug: &str,
3080        version: &str,
3081    ) -> Result<presets::PresetDesignatedVersion, OpenRouterError> {
3082        self.client.get_preset_version(slug, version).await
3083    }
3084
3085    /// Delete an API key (`DELETE /keys/{hash}`).
3086    pub async fn delete_api_key(&self, hash: &str) -> Result<bool, OpenRouterError> {
3087        self.client.delete_api_key(hash).await
3088    }
3089
3090    /// Update an API key (`PATCH /keys/{hash}`).
3091    pub async fn update_api_key(
3092        &self,
3093        hash: &str,
3094        name: Option<String>,
3095        disabled: Option<bool>,
3096        limit: Option<f64>,
3097    ) -> Result<api_keys::ApiKey, OpenRouterError> {
3098        self.client
3099            .update_api_key(hash, name, disabled, limit)
3100            .await
3101    }
3102
3103    /// List API keys (`GET /keys`).
3104    pub async fn list_api_keys(
3105        &self,
3106        pagination: Option<PaginationOptions>,
3107        include_disabled: Option<bool>,
3108    ) -> Result<Vec<api_keys::ApiKey>, OpenRouterError> {
3109        self.client
3110            .list_api_keys_paginated(pagination, include_disabled)
3111            .await
3112    }
3113
3114    /// List API keys scoped to a workspace (`GET /keys?workspace_id=...`).
3115    pub async fn list_api_keys_in_workspace(
3116        &self,
3117        pagination: Option<PaginationOptions>,
3118        include_disabled: Option<bool>,
3119        workspace_id: Option<&str>,
3120    ) -> Result<Vec<api_keys::ApiKey>, OpenRouterError> {
3121        self.client
3122            .list_api_keys_in_workspace_paginated(pagination, include_disabled, workspace_id)
3123            .await
3124    }
3125
3126    /// Get an API key (`GET /keys/{hash}`).
3127    pub async fn get_api_key(&self, hash: &str) -> Result<api_keys::ApiKey, OpenRouterError> {
3128        self.client.get_api_key(hash).await
3129    }
3130
3131    /// Create OAuth auth code (`POST /auth/keys/code`).
3132    pub async fn create_auth_code(
3133        &self,
3134        request: &auth::CreateAuthCodeRequest,
3135    ) -> Result<auth::AuthCodeData, OpenRouterError> {
3136        self.client.create_auth_code(request).await
3137    }
3138
3139    /// Create an API key from auth code (`POST /auth/keys`).
3140    pub async fn create_api_key_from_auth_code(
3141        &self,
3142        code: &str,
3143        code_verifier: Option<&str>,
3144        code_challenge_method: Option<auth::CodeChallengeMethod>,
3145    ) -> Result<auth::AuthResponse, OpenRouterError> {
3146        self.client
3147            .exchange_code_for_api_key(code, code_verifier, code_challenge_method)
3148            .await
3149    }
3150
3151    /// Create a Coinbase charge (`POST /credits/coinbase`).
3152    pub async fn create_coinbase_charge(
3153        &self,
3154        request: &credits::CoinbaseChargeRequest,
3155    ) -> Result<credits::CoinbaseChargeData, OpenRouterError> {
3156        self.client.create_coinbase_charge(request).await
3157    }
3158
3159    /// Get credits (`GET /credits`).
3160    pub async fn get_credits(&self) -> Result<credits::CreditsData, OpenRouterError> {
3161        self.client.get_credits().await
3162    }
3163
3164    /// Get generation metadata (`GET /generation?id=...`).
3165    pub async fn get_generation(
3166        &self,
3167        id: impl Into<String>,
3168    ) -> Result<generation::GenerationData, OpenRouterError> {
3169        self.client.get_generation(id).await
3170    }
3171
3172    /// Get stored generation content (`GET /generation/content?id=...`).
3173    pub async fn get_generation_content(
3174        &self,
3175        id: impl Into<String>,
3176    ) -> Result<generation::GenerationContentData, OpenRouterError> {
3177        self.client.get_generation_content(id).await
3178    }
3179
3180    /// Get endpoint usage activity (`GET /activity`).
3181    pub async fn get_activity(
3182        &self,
3183        date: Option<&str>,
3184    ) -> Result<Vec<discovery::ActivityItem>, OpenRouterError> {
3185        self.client.get_activity(date).await
3186    }
3187
3188    /// Get analytics metadata (`GET /analytics/meta`).
3189    pub async fn get_analytics_meta(&self) -> Result<analytics::AnalyticsMeta, OpenRouterError> {
3190        self.client.get_analytics_meta().await
3191    }
3192
3193    /// Query analytics (`POST /analytics/query`).
3194    pub async fn query_analytics(
3195        &self,
3196        request: &analytics::AnalyticsQueryRequest,
3197    ) -> Result<analytics::AnalyticsQueryResponse, OpenRouterError> {
3198        self.client.query_analytics(request).await
3199    }
3200
3201    /// List BYOK provider credentials (`GET /byok`).
3202    pub async fn list_byok_keys(
3203        &self,
3204        pagination: Option<PaginationOptions>,
3205        workspace_id: Option<&str>,
3206        provider: Option<&str>,
3207    ) -> Result<byok::ByokKeyListResponse, OpenRouterError> {
3208        self.client
3209            .list_byok_keys(pagination, workspace_id, provider)
3210            .await
3211    }
3212
3213    /// Create a BYOK provider credential (`POST /byok`).
3214    pub async fn create_byok_key(
3215        &self,
3216        request: &byok::CreateByokKeyRequest,
3217    ) -> Result<byok::ByokKey, OpenRouterError> {
3218        self.client.create_byok_key(request).await
3219    }
3220
3221    /// Get a BYOK provider credential (`GET /byok/{id}`).
3222    pub async fn get_byok_key(&self, id: &str) -> Result<byok::ByokKey, OpenRouterError> {
3223        self.client.get_byok_key(id).await
3224    }
3225
3226    /// Update a BYOK provider credential (`PATCH /byok/{id}`).
3227    pub async fn update_byok_key(
3228        &self,
3229        id: &str,
3230        request: &byok::UpdateByokKeyRequest,
3231    ) -> Result<byok::ByokKey, OpenRouterError> {
3232        self.client.update_byok_key(id, request).await
3233    }
3234
3235    /// Delete a BYOK provider credential (`DELETE /byok/{id}`).
3236    pub async fn delete_byok_key(&self, id: &str) -> Result<bool, OpenRouterError> {
3237        self.client.delete_byok_key(id).await
3238    }
3239
3240    /// List observability destinations (`GET /observability/destinations`).
3241    pub async fn list_observability_destinations(
3242        &self,
3243        pagination: Option<PaginationOptions>,
3244        workspace_id: Option<&str>,
3245    ) -> Result<observability::ObservabilityDestinationListResponse, OpenRouterError> {
3246        self.client
3247            .list_observability_destinations(pagination, workspace_id)
3248            .await
3249    }
3250
3251    /// Create an observability destination (`POST /observability/destinations`).
3252    pub async fn create_observability_destination(
3253        &self,
3254        request: &observability::CreateObservabilityDestinationRequest,
3255    ) -> Result<observability::ObservabilityDestination, OpenRouterError> {
3256        self.client.create_observability_destination(request).await
3257    }
3258
3259    /// Get an observability destination (`GET /observability/destinations/{id}`).
3260    pub async fn get_observability_destination(
3261        &self,
3262        id: &str,
3263    ) -> Result<observability::ObservabilityDestination, OpenRouterError> {
3264        self.client.get_observability_destination(id).await
3265    }
3266
3267    /// Update an observability destination (`PATCH /observability/destinations/{id}`).
3268    pub async fn update_observability_destination(
3269        &self,
3270        id: &str,
3271        request: &observability::UpdateObservabilityDestinationRequest,
3272    ) -> Result<observability::ObservabilityDestination, OpenRouterError> {
3273        self.client
3274            .update_observability_destination(id, request)
3275            .await
3276    }
3277
3278    /// Delete an observability destination (`DELETE /observability/destinations/{id}`).
3279    pub async fn delete_observability_destination(
3280        &self,
3281        id: &str,
3282    ) -> Result<bool, OpenRouterError> {
3283        self.client.delete_observability_destination(id).await
3284    }
3285
3286    /// List guardrails (`GET /guardrails`).
3287    pub async fn list_guardrails(
3288        &self,
3289        pagination: Option<PaginationOptions>,
3290    ) -> Result<guardrails::GuardrailListResponse, OpenRouterError> {
3291        self.client.list_guardrails(pagination).await
3292    }
3293
3294    /// List guardrails scoped to a workspace (`GET /guardrails?workspace_id=...`).
3295    pub async fn list_guardrails_in_workspace(
3296        &self,
3297        pagination: Option<PaginationOptions>,
3298        workspace_id: Option<&str>,
3299    ) -> Result<guardrails::GuardrailListResponse, OpenRouterError> {
3300        self.client
3301            .list_guardrails_in_workspace(pagination, workspace_id)
3302            .await
3303    }
3304
3305    /// Create a guardrail (`POST /guardrails`).
3306    pub async fn create_guardrail(
3307        &self,
3308        request: &guardrails::CreateGuardrailRequest,
3309    ) -> Result<guardrails::Guardrail, OpenRouterError> {
3310        self.client.create_guardrail(request).await
3311    }
3312
3313    /// Get a guardrail (`GET /guardrails/{id}`).
3314    pub async fn get_guardrail(&self, id: &str) -> Result<guardrails::Guardrail, OpenRouterError> {
3315        self.client.get_guardrail(id).await
3316    }
3317
3318    /// Update a guardrail (`PATCH /guardrails/{id}`).
3319    pub async fn update_guardrail(
3320        &self,
3321        id: &str,
3322        request: &guardrails::UpdateGuardrailRequest,
3323    ) -> Result<guardrails::Guardrail, OpenRouterError> {
3324        self.client.update_guardrail(id, request).await
3325    }
3326
3327    /// Delete a guardrail (`DELETE /guardrails/{id}`).
3328    pub async fn delete_guardrail(&self, id: &str) -> Result<bool, OpenRouterError> {
3329        self.client.delete_guardrail(id).await
3330    }
3331
3332    /// List key assignments for a guardrail.
3333    pub async fn list_guardrail_key_assignments(
3334        &self,
3335        id: &str,
3336        pagination: Option<PaginationOptions>,
3337    ) -> Result<guardrails::GuardrailKeyAssignmentsResponse, OpenRouterError> {
3338        self.client
3339            .list_guardrail_key_assignments(id, pagination)
3340            .await
3341    }
3342
3343    /// Create key assignments for a guardrail.
3344    pub async fn create_guardrail_key_assignments(
3345        &self,
3346        id: &str,
3347        request: &guardrails::BulkKeyAssignmentRequest,
3348    ) -> Result<guardrails::AssignedCountResponse, OpenRouterError> {
3349        self.client.bulk_assign_keys_to_guardrail(id, request).await
3350    }
3351
3352    /// Delete key assignments from a guardrail.
3353    pub async fn delete_guardrail_key_assignments(
3354        &self,
3355        id: &str,
3356        request: &guardrails::BulkKeyAssignmentRequest,
3357    ) -> Result<guardrails::UnassignedCountResponse, OpenRouterError> {
3358        self.client
3359            .bulk_unassign_keys_from_guardrail(id, request)
3360            .await
3361    }
3362
3363    /// List member assignments for a guardrail.
3364    pub async fn list_guardrail_member_assignments(
3365        &self,
3366        id: &str,
3367        pagination: Option<PaginationOptions>,
3368    ) -> Result<guardrails::GuardrailMemberAssignmentsResponse, OpenRouterError> {
3369        self.client
3370            .list_guardrail_member_assignments(id, pagination)
3371            .await
3372    }
3373
3374    /// Create member assignments for a guardrail.
3375    pub async fn create_guardrail_member_assignments(
3376        &self,
3377        id: &str,
3378        request: &guardrails::BulkMemberAssignmentRequest,
3379    ) -> Result<guardrails::AssignedCountResponse, OpenRouterError> {
3380        self.client
3381            .bulk_assign_members_to_guardrail(id, request)
3382            .await
3383    }
3384
3385    /// Delete member assignments from a guardrail.
3386    pub async fn delete_guardrail_member_assignments(
3387        &self,
3388        id: &str,
3389        request: &guardrails::BulkMemberAssignmentRequest,
3390    ) -> Result<guardrails::UnassignedCountResponse, OpenRouterError> {
3391        self.client
3392            .bulk_unassign_members_from_guardrail(id, request)
3393            .await
3394    }
3395
3396    /// List global key assignments.
3397    pub async fn list_key_assignments(
3398        &self,
3399        pagination: Option<PaginationOptions>,
3400    ) -> Result<guardrails::GuardrailKeyAssignmentsResponse, OpenRouterError> {
3401        self.client.list_key_assignments(pagination).await
3402    }
3403
3404    /// List global member assignments.
3405    pub async fn list_member_assignments(
3406        &self,
3407        pagination: Option<PaginationOptions>,
3408    ) -> Result<guardrails::GuardrailMemberAssignmentsResponse, OpenRouterError> {
3409        self.client.list_member_assignments(pagination).await
3410    }
3411
3412    /// List organization members (`GET /organization/members`).
3413    pub async fn list_organization_members(
3414        &self,
3415        pagination: Option<PaginationOptions>,
3416    ) -> Result<organization::OrganizationMembersResponse, OpenRouterError> {
3417        self.client.list_organization_members(pagination).await
3418    }
3419
3420    /// List workspaces (`GET /workspaces`).
3421    pub async fn list_workspaces(
3422        &self,
3423        pagination: Option<PaginationOptions>,
3424    ) -> Result<workspaces::WorkspaceListResponse, OpenRouterError> {
3425        self.client.list_workspaces(pagination).await
3426    }
3427
3428    /// Create a workspace (`POST /workspaces`).
3429    pub async fn create_workspace(
3430        &self,
3431        request: &workspaces::CreateWorkspaceRequest,
3432    ) -> Result<workspaces::Workspace, OpenRouterError> {
3433        self.client.create_workspace(request).await
3434    }
3435
3436    /// Get a workspace (`GET /workspaces/{id}`).
3437    pub async fn get_workspace(&self, id: &str) -> Result<workspaces::Workspace, OpenRouterError> {
3438        self.client.get_workspace(id).await
3439    }
3440
3441    /// Update a workspace (`PATCH /workspaces/{id}`).
3442    pub async fn update_workspace(
3443        &self,
3444        id: &str,
3445        request: &workspaces::UpdateWorkspaceRequest,
3446    ) -> Result<workspaces::Workspace, OpenRouterError> {
3447        self.client.update_workspace(id, request).await
3448    }
3449
3450    /// Update a workspace and clear I/O logging API key filters (`PATCH /workspaces/{id}`).
3451    pub async fn update_workspace_with_cleared_io_logging_api_key_ids(
3452        &self,
3453        id: &str,
3454        request: &workspaces::UpdateWorkspaceRequest,
3455    ) -> Result<workspaces::Workspace, OpenRouterError> {
3456        self.client
3457            .update_workspace_with_cleared_io_logging_api_key_ids(id, request)
3458            .await
3459    }
3460
3461    /// Delete a workspace (`DELETE /workspaces/{id}`).
3462    pub async fn delete_workspace(&self, id: &str) -> Result<bool, OpenRouterError> {
3463        self.client.delete_workspace(id).await
3464    }
3465
3466    /// List budgets for a workspace (`GET /workspaces/{id}/budgets`).
3467    pub async fn list_workspace_budgets(
3468        &self,
3469        id: &str,
3470    ) -> Result<workspaces::ListWorkspaceBudgetsResponse, OpenRouterError> {
3471        self.client.list_workspace_budgets(id).await
3472    }
3473
3474    /// Create or update a workspace budget (`PUT /workspaces/{id}/budgets/{interval}`).
3475    pub async fn upsert_workspace_budget(
3476        &self,
3477        id: &str,
3478        interval: &str,
3479        request: &workspaces::UpsertWorkspaceBudgetRequest,
3480    ) -> Result<workspaces::WorkspaceBudget, OpenRouterError> {
3481        self.client
3482            .upsert_workspace_budget(id, interval, request)
3483            .await
3484    }
3485
3486    /// Delete a workspace budget (`DELETE /workspaces/{id}/budgets/{interval}`).
3487    pub async fn delete_workspace_budget(
3488        &self,
3489        id: &str,
3490        interval: &str,
3491    ) -> Result<bool, OpenRouterError> {
3492        self.client.delete_workspace_budget(id, interval).await
3493    }
3494
3495    /// Add workspace members (`POST /workspaces/{id}/members/add`).
3496    pub async fn add_workspace_members(
3497        &self,
3498        id: &str,
3499        request: &workspaces::WorkspaceMembersRequest,
3500    ) -> Result<workspaces::WorkspaceMembersAddResponse, OpenRouterError> {
3501        self.client.add_workspace_members(id, request).await
3502    }
3503
3504    /// Remove workspace members (`POST /workspaces/{id}/members/remove`).
3505    pub async fn remove_workspace_members(
3506        &self,
3507        id: &str,
3508        request: &workspaces::WorkspaceMembersRequest,
3509    ) -> Result<workspaces::WorkspaceMembersRemoveResponse, OpenRouterError> {
3510        self.client.remove_workspace_members(id, request).await
3511    }
3512}
3513
3514/// Domain client for legacy APIs (`legacy-completions` feature only).
3515#[cfg(feature = "legacy-completions")]
3516#[derive(Debug, Clone, Copy)]
3517pub struct LegacyClient<'a> {
3518    client: &'a OpenRouterClient,
3519}
3520
3521#[cfg(feature = "legacy-completions")]
3522impl<'a> LegacyClient<'a> {
3523    /// Domain client for legacy text completions (`POST /completions`).
3524    pub fn completions(&self) -> LegacyCompletionsClient<'a> {
3525        LegacyCompletionsClient {
3526            client: self.client,
3527        }
3528    }
3529}
3530
3531/// Domain client for legacy text completions (`legacy-completions` feature only).
3532#[cfg(feature = "legacy-completions")]
3533#[derive(Debug, Clone, Copy)]
3534pub struct LegacyCompletionsClient<'a> {
3535    client: &'a OpenRouterClient,
3536}
3537
3538#[cfg(feature = "legacy-completions")]
3539impl<'a> LegacyCompletionsClient<'a> {
3540    /// Create a legacy text completion (`POST /completions`).
3541    pub async fn create(
3542        &self,
3543        request: &completion::CompletionRequest,
3544    ) -> Result<CompletionsResponse, OpenRouterError> {
3545        if let Some(api_key) = &self.client.api_key {
3546            completion::send_completion_request_with_client(
3547                self.client.http_client(),
3548                &self.client.base_url,
3549                api_key,
3550                &self.client.x_title,
3551                &self.client.http_referer,
3552                &self.client.app_categories,
3553                request,
3554            )
3555            .await
3556        } else {
3557            Err(OpenRouterError::KeyNotConfigured)
3558        }
3559    }
3560}