Skip to main content

openrouter/types/
account.rs

1//! Response types for the account endpoints (`/credits`, `/key`, `/activity`,
2//! `/keys` CRUD).
3//!
4//! Shapes mirror the Go SDK (`account_models.go`) one-for-one.
5
6use serde::{Deserialize, Serialize};
7
8/// Response from `GET /credits`.
9#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
10pub struct CreditsResponse {
11    /// Credit-balance payload.
12    #[serde(default)]
13    pub data: CreditsData,
14}
15
16/// Credit balance for the authenticated user.
17#[derive(Clone, Copy, Debug, Default, PartialEq, Serialize, Deserialize)]
18pub struct CreditsData {
19    /// Total purchased credits in USD.
20    #[serde(default)]
21    pub total_credits: f64,
22    /// Lifetime usage in USD.
23    #[serde(default)]
24    pub total_usage: f64,
25}
26
27impl CreditsData {
28    /// Remaining balance (`total_credits - total_usage`).
29    pub fn remaining(&self) -> f64 {
30        self.total_credits - self.total_usage
31    }
32}
33
34/// Response from `GET /key`.
35#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
36pub struct KeyResponse {
37    /// Key-info payload.
38    #[serde(default)]
39    pub data: KeyData,
40}
41
42/// Information about the current API key.
43#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
44pub struct KeyData {
45    /// Display label for the key.
46    #[serde(default)]
47    pub label: String,
48    /// Configured spend limit. `None` if no limit is set.
49    #[serde(default)]
50    pub limit: Option<f64>,
51    /// Lifetime usage in USD.
52    #[serde(default)]
53    pub usage: f64,
54    /// True if the key is on the free tier.
55    #[serde(default)]
56    pub is_free_tier: bool,
57    /// Remaining spend allowance. `None` when no limit is set.
58    #[serde(default)]
59    pub limit_remaining: Option<f64>,
60    /// `true` if this is a provisioning key (can manage other keys).
61    #[serde(default)]
62    pub is_provisioning_key: bool,
63    /// Rate-limit applied to this key, when set.
64    #[serde(default)]
65    pub rate_limit: Option<KeyRateLimit>,
66}
67
68/// Optional query parameters for [`crate::Client::get_activity`].
69#[derive(Clone, Debug, Default, PartialEq, Eq)]
70pub struct ActivityOptions {
71    /// Single UTC date (`YYYY-MM-DD`) within the last 30 days. The API still
72    /// returns the timestamped date string in the response.
73    pub date: Option<String>,
74}
75
76impl ActivityOptions {
77    /// Construct an empty options struct.
78    pub fn new() -> Self {
79        Self::default()
80    }
81
82    /// Builder: set [`Self::date`].
83    pub fn date(mut self, date: impl Into<String>) -> Self {
84        self.date = Some(date.into());
85        self
86    }
87
88    pub(crate) fn to_query(&self) -> Vec<(&'static str, String)> {
89        let mut q = Vec::new();
90        if let Some(d) = &self.date {
91            q.push(("date", d.clone()));
92        }
93        q
94    }
95}
96
97/// Response from `GET /activity`.
98#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
99pub struct ActivityResponse {
100    /// Per-row activity data.
101    #[serde(default)]
102    pub data: Vec<ActivityData>,
103}
104
105/// One row of daily activity grouped by model endpoint.
106#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
107pub struct ActivityData {
108    /// UTC date of the row.
109    #[serde(default)]
110    pub date: String,
111    /// Model id.
112    #[serde(default)]
113    pub model: String,
114    /// Stable model permaslug (immutable across renames).
115    #[serde(default)]
116    pub model_permaslug: String,
117    /// Endpoint identifier within the model.
118    #[serde(default)]
119    pub endpoint_id: String,
120    /// Provider that served the requests.
121    #[serde(default)]
122    pub provider_name: String,
123    /// USD spent on this row.
124    #[serde(default)]
125    pub usage: f64,
126    /// USD spent on BYOK inference (not deducted from credits).
127    #[serde(default)]
128    pub byok_usage_inference: f64,
129    /// Request count.
130    #[serde(default)]
131    pub requests: f64,
132    /// Prompt tokens.
133    #[serde(default)]
134    pub prompt_tokens: f64,
135    /// Completion tokens.
136    #[serde(default)]
137    pub completion_tokens: f64,
138    /// Reasoning tokens.
139    #[serde(default)]
140    pub reasoning_tokens: f64,
141}
142
143/// Optional query parameters for [`crate::Client::list_keys`].
144#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
145pub struct ListKeysOptions {
146    /// Pagination offset.
147    pub offset: Option<u32>,
148    /// Include disabled keys in the response.
149    pub include_disabled: Option<bool>,
150}
151
152impl ListKeysOptions {
153    /// Construct an empty options struct.
154    pub fn new() -> Self {
155        Self::default()
156    }
157
158    /// Builder: set [`Self::offset`].
159    pub fn offset(mut self, offset: u32) -> Self {
160        self.offset = Some(offset);
161        self
162    }
163
164    /// Builder: set [`Self::include_disabled`].
165    pub fn include_disabled(mut self, include: bool) -> Self {
166        self.include_disabled = Some(include);
167        self
168    }
169
170    pub(crate) fn to_query(self) -> Vec<(&'static str, String)> {
171        let mut q = Vec::new();
172        if let Some(o) = self.offset {
173            q.push(("offset", o.to_string()));
174        }
175        if let Some(i) = self.include_disabled {
176            q.push(("include_disabled", i.to_string()));
177        }
178        q
179    }
180}
181
182/// Response from `GET /keys`.
183#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
184pub struct ListKeysResponse {
185    /// Key rows returned by the server.
186    #[serde(default)]
187    pub data: Vec<ApiKey>,
188}
189
190/// Metadata for a single API key as returned by the provisioning endpoints.
191///
192/// Note: the secret key value is only ever returned once, in
193/// [`CreateKeyResponse::key`].
194#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
195pub struct ApiKey {
196    /// Display name.
197    #[serde(default)]
198    pub name: String,
199    /// Internal label (often equals `name`).
200    #[serde(default)]
201    pub label: String,
202    /// Spend limit in USD (0 means unlimited).
203    #[serde(default)]
204    pub limit: f64,
205    /// True if the key is disabled.
206    #[serde(default)]
207    pub disabled: bool,
208    /// Creation timestamp.
209    #[serde(default)]
210    pub created_at: String,
211    /// Last-update timestamp.
212    #[serde(default)]
213    pub updated_at: String,
214    /// Stable identifier for the key. Use this to address the key in
215    /// [`crate::Client::get_key_by_hash`], [`crate::Client::update_key`], and
216    /// [`crate::Client::delete_key`].
217    #[serde(default)]
218    pub hash: String,
219}
220
221/// Request body for [`crate::Client::create_key`].
222#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
223pub struct CreateKeyRequest {
224    /// Required label / display name for the key.
225    pub name: String,
226    /// Optional credit limit (in dollars).
227    #[serde(skip_serializing_if = "Option::is_none", default)]
228    pub limit: Option<f64>,
229    /// When true, BYOK usage counts toward `limit`.
230    #[serde(skip_serializing_if = "Option::is_none", default)]
231    pub include_byok_in_limit: Option<bool>,
232}
233
234/// Response from `POST /keys` — the only place the secret key is ever
235/// returned. Store it immediately; it cannot be recovered later.
236#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
237pub struct CreateKeyResponse {
238    /// Key metadata.
239    #[serde(default)]
240    pub data: ApiKey,
241    /// Secret API key value. **Returned only on creation.** `None` from any
242    /// other endpoint.
243    #[serde(default, skip_serializing_if = "Option::is_none")]
244    pub key: Option<String>,
245}
246
247/// Response from `GET /keys/{hash}`.
248#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
249pub struct GetKeyByHashResponse {
250    /// Key metadata.
251    #[serde(default)]
252    pub data: ApiKey,
253}
254
255/// Partial-update request body for [`crate::Client::update_key`]. Only the
256/// fields you set are sent.
257#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
258pub struct UpdateKeyRequest {
259    /// New display name.
260    #[serde(skip_serializing_if = "Option::is_none", default)]
261    pub name: Option<String>,
262    /// New disabled flag.
263    #[serde(skip_serializing_if = "Option::is_none", default)]
264    pub disabled: Option<bool>,
265    /// New spend limit.
266    #[serde(skip_serializing_if = "Option::is_none", default)]
267    pub limit: Option<f64>,
268    /// New BYOK-counts-toward-limit flag.
269    #[serde(skip_serializing_if = "Option::is_none", default)]
270    pub include_byok_in_limit: Option<bool>,
271}
272
273/// Response from `PATCH /keys/{hash}`.
274#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
275pub struct UpdateKeyResponse {
276    /// Updated key metadata.
277    #[serde(default)]
278    pub data: ApiKey,
279}
280
281/// Response from `DELETE /keys/{hash}`.
282#[derive(Clone, Copy, Debug, Default, PartialEq, Serialize, Deserialize)]
283pub struct DeleteKeyResponse {
284    /// Deletion outcome.
285    #[serde(default)]
286    pub data: DeleteKeyData,
287}
288
289/// Deletion outcome carried by [`DeleteKeyResponse`].
290#[derive(Clone, Copy, Debug, Default, PartialEq, Serialize, Deserialize)]
291pub struct DeleteKeyData {
292    /// True when the key existed and was deleted.
293    #[serde(default)]
294    pub success: bool,
295}
296
297/// Rate limit applied to an API key.
298#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
299pub struct KeyRateLimit {
300    /// Window (e.g. `"10s"`).
301    #[serde(default)]
302    pub interval: String,
303    /// Allowed requests per [`Self::interval`].
304    #[serde(default)]
305    pub requests: f64,
306}