Skip to main content

openrouter/types/
guardrails.rs

1//! Types for the guardrails endpoints (`/guardrails`) and ZDR endpoint
2//! listing (`/endpoints/zdr`).
3//!
4//! Shapes mirror the Go SDK (`guardrails_models.go`, `metadata_models.go`).
5//! All endpoints in this module require a **provisioning (management) API
6//! key**.
7
8use serde::{Deserialize, Serialize};
9
10/// Reset interval for a guardrail's spend budget.
11#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
12#[serde(rename_all = "lowercase")]
13pub enum ResetInterval {
14    /// Reset every day at midnight UTC.
15    Daily,
16    /// Reset weekly.
17    Weekly,
18    /// Reset monthly.
19    Monthly,
20}
21
22/// A guardrail configuration controlling spending, model access, and data
23/// policies.
24#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
25pub struct Guardrail {
26    /// Stable guardrail identifier.
27    #[serde(default)]
28    pub id: String,
29    /// Human-readable name.
30    #[serde(default)]
31    pub name: String,
32    /// Free-form description.
33    #[serde(default)]
34    pub description: Option<String>,
35    /// Spend cap in USD, evaluated against [`Self::reset_interval`].
36    #[serde(default)]
37    pub limit_usd: Option<f64>,
38    /// Reset cadence for [`Self::limit_usd`].
39    #[serde(default)]
40    pub reset_interval: Option<ResetInterval>,
41    /// Allowlist of provider slugs; empty means "all providers".
42    #[serde(default)]
43    pub allowed_providers: Vec<String>,
44    /// Allowlist of model ids; empty means "all models".
45    #[serde(default)]
46    pub allowed_models: Vec<String>,
47    /// When true, require ZDR-certified endpoints.
48    #[serde(default)]
49    pub enforce_zdr: Option<bool>,
50    /// Creation timestamp.
51    #[serde(default)]
52    pub created_at: String,
53    /// Last-update timestamp.
54    #[serde(default)]
55    pub updated_at: Option<String>,
56}
57
58/// Optional query parameters for the guardrails listing endpoints (also
59/// reused for the key/member assignment listings).
60#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
61pub struct ListGuardrailsOptions {
62    /// Skip this many rows before returning results.
63    pub offset: Option<u32>,
64    /// Cap on the number of rows returned.
65    pub limit: Option<u32>,
66}
67
68impl ListGuardrailsOptions {
69    /// Construct an empty options struct.
70    pub fn new() -> Self {
71        Self::default()
72    }
73
74    /// Builder: set [`Self::offset`].
75    pub fn offset(mut self, offset: u32) -> Self {
76        self.offset = Some(offset);
77        self
78    }
79
80    /// Builder: set [`Self::limit`].
81    pub fn limit(mut self, limit: u32) -> Self {
82        self.limit = Some(limit);
83        self
84    }
85
86    pub(crate) fn to_query(self) -> Vec<(&'static str, String)> {
87        let mut q = Vec::new();
88        if let Some(o) = self.offset {
89            q.push(("offset", o.to_string()));
90        }
91        if let Some(l) = self.limit {
92            q.push(("limit", l.to_string()));
93        }
94        q
95    }
96}
97
98/// Response from `GET /guardrails`.
99#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
100pub struct ListGuardrailsResponse {
101    /// The guardrail rows returned by the server.
102    #[serde(default)]
103    pub data: Vec<Guardrail>,
104    /// Total row count, ignoring pagination.
105    #[serde(default)]
106    pub total_count: u64,
107}
108
109/// Request body for [`crate::Client::create_guardrail`]. `name` is required.
110#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
111pub struct CreateGuardrailRequest {
112    /// Display name for the new guardrail.
113    pub name: String,
114    /// Optional description.
115    #[serde(skip_serializing_if = "Option::is_none", default)]
116    pub description: Option<String>,
117    /// Optional spend limit in USD.
118    #[serde(skip_serializing_if = "Option::is_none", default)]
119    pub limit_usd: Option<f64>,
120    /// Reset cadence for [`Self::limit_usd`].
121    #[serde(skip_serializing_if = "Option::is_none", default)]
122    pub reset_interval: Option<ResetInterval>,
123    /// Provider allowlist; empty means "all".
124    #[serde(skip_serializing_if = "Vec::is_empty", default)]
125    pub allowed_providers: Vec<String>,
126    /// Model allowlist; empty means "all".
127    #[serde(skip_serializing_if = "Vec::is_empty", default)]
128    pub allowed_models: Vec<String>,
129    /// Require ZDR-certified endpoints.
130    #[serde(skip_serializing_if = "Option::is_none", default)]
131    pub enforce_zdr: Option<bool>,
132}
133
134/// Partial-update body for [`crate::Client::update_guardrail`]. All fields
135/// are optional; only set fields are sent.
136#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
137pub struct UpdateGuardrailRequest {
138    /// New name.
139    #[serde(skip_serializing_if = "Option::is_none", default)]
140    pub name: Option<String>,
141    /// New description.
142    #[serde(skip_serializing_if = "Option::is_none", default)]
143    pub description: Option<String>,
144    /// New spend limit in USD.
145    #[serde(skip_serializing_if = "Option::is_none", default)]
146    pub limit_usd: Option<f64>,
147    /// New reset cadence.
148    #[serde(skip_serializing_if = "Option::is_none", default)]
149    pub reset_interval: Option<ResetInterval>,
150    /// New provider allowlist.
151    #[serde(skip_serializing_if = "Vec::is_empty", default)]
152    pub allowed_providers: Vec<String>,
153    /// New model allowlist.
154    #[serde(skip_serializing_if = "Vec::is_empty", default)]
155    pub allowed_models: Vec<String>,
156    /// New ZDR enforcement flag.
157    #[serde(skip_serializing_if = "Option::is_none", default)]
158    pub enforce_zdr: Option<bool>,
159}
160
161/// Response from `DELETE /guardrails/{id}`.
162#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
163pub struct DeleteGuardrailResponse {
164    /// True when the guardrail existed and was deleted.
165    #[serde(default)]
166    pub deleted: bool,
167}
168
169/// An API key assignment to a guardrail.
170#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
171pub struct GuardrailKeyAssignment {
172    /// Assignment identifier.
173    #[serde(default)]
174    pub id: String,
175    /// Hash of the assigned API key.
176    #[serde(default)]
177    pub key_hash: String,
178    /// Organization that owns the assignment.
179    #[serde(default)]
180    pub organization_id: String,
181    /// Guardrail the key is assigned to.
182    #[serde(default)]
183    pub guardrail_id: String,
184    /// User id of whoever created the assignment, when known.
185    #[serde(default)]
186    pub assigned_by: Option<String>,
187    /// Creation timestamp.
188    #[serde(default)]
189    pub created_at: String,
190}
191
192/// Response from key-assignment listings.
193#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
194pub struct ListGuardrailKeyAssignmentsResponse {
195    /// Assignment rows returned by the server.
196    #[serde(default)]
197    pub data: Vec<GuardrailKeyAssignment>,
198    /// Total row count, ignoring pagination.
199    #[serde(default)]
200    pub total_count: u64,
201}
202
203/// Request body for [`crate::Client::assign_keys_to_guardrail`] and
204/// [`crate::Client::unassign_keys_from_guardrail`].
205#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
206pub struct AssignKeysRequest {
207    /// Hashes of the keys to assign or unassign.
208    pub key_hashes: Vec<String>,
209}
210
211/// Response from [`crate::Client::assign_keys_to_guardrail`].
212#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
213pub struct AssignKeysResponse {
214    /// Number of keys whose assignment changed.
215    #[serde(default)]
216    pub assigned_count: u64,
217}
218
219/// A member assignment to a guardrail.
220#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
221pub struct GuardrailMemberAssignment {
222    /// Assignment identifier.
223    #[serde(default)]
224    pub id: String,
225    /// User id of the assigned member.
226    #[serde(default)]
227    pub user_id: String,
228    /// Organization that owns the assignment.
229    #[serde(default)]
230    pub organization_id: String,
231    /// Guardrail the member is assigned to.
232    #[serde(default)]
233    pub guardrail_id: String,
234    /// User id of whoever created the assignment, when known.
235    #[serde(default)]
236    pub assigned_by: Option<String>,
237    /// Creation timestamp.
238    #[serde(default)]
239    pub created_at: String,
240}
241
242/// Response from member-assignment listings.
243#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
244pub struct ListGuardrailMemberAssignmentsResponse {
245    /// Assignment rows returned by the server.
246    #[serde(default)]
247    pub data: Vec<GuardrailMemberAssignment>,
248    /// Total row count, ignoring pagination.
249    #[serde(default)]
250    pub total_count: u64,
251}
252
253/// Request body for [`crate::Client::assign_members_to_guardrail`] and
254/// [`crate::Client::unassign_members_from_guardrail`].
255#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
256pub struct AssignMembersRequest {
257    /// User ids to assign or unassign.
258    pub member_user_ids: Vec<String>,
259}
260
261/// Response from [`crate::Client::assign_members_to_guardrail`].
262#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
263pub struct AssignMembersResponse {
264    /// Number of members whose assignment changed.
265    #[serde(default)]
266    pub assigned_count: u64,
267}
268
269// ---- ZDR endpoints (`GET /endpoints/zdr`) ----
270
271/// Latency or throughput percentile statistics for a public endpoint.
272#[derive(Clone, Copy, Debug, Default, PartialEq, Serialize, Deserialize)]
273pub struct PercentileStats {
274    /// 50th percentile.
275    #[serde(default)]
276    pub p50: f64,
277    /// 75th percentile.
278    #[serde(default)]
279    pub p75: f64,
280    /// 90th percentile.
281    #[serde(default)]
282    pub p90: f64,
283    /// 99th percentile.
284    #[serde(default)]
285    pub p99: f64,
286}
287
288/// Pricing information for a public endpoint (used by the ZDR listing).
289#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
290pub struct PublicEndpointPricing {
291    /// Per-prompt-token cost as a decimal string in USD.
292    #[serde(default)]
293    pub prompt: String,
294    /// Per-completion-token cost as a decimal string in USD.
295    #[serde(default)]
296    pub completion: String,
297    /// Per-request flat fee, when applicable.
298    #[serde(default, skip_serializing_if = "String::is_empty")]
299    pub request: String,
300    /// Per-image cost, when applicable.
301    #[serde(default, skip_serializing_if = "String::is_empty")]
302    pub image: String,
303    /// Per-image-input-token cost, when applicable.
304    #[serde(default, skip_serializing_if = "String::is_empty")]
305    pub image_token: String,
306    /// Per-image-output cost, when applicable.
307    #[serde(default, skip_serializing_if = "String::is_empty")]
308    pub image_output: String,
309    /// Per-second-of-audio-input cost, when applicable.
310    #[serde(default, skip_serializing_if = "String::is_empty")]
311    pub audio: String,
312    /// Per-second-of-audio-output cost, when applicable.
313    #[serde(default, skip_serializing_if = "String::is_empty")]
314    pub audio_output: String,
315    /// Audio-input cache pricing.
316    #[serde(default, skip_serializing_if = "String::is_empty")]
317    pub input_audio_cache: String,
318    /// Web-search invocation pricing.
319    #[serde(default, skip_serializing_if = "String::is_empty")]
320    pub web_search: String,
321    /// Per-internal-reasoning-token cost, when applicable.
322    #[serde(default, skip_serializing_if = "String::is_empty")]
323    pub internal_reasoning: String,
324    /// Cached-input read pricing.
325    #[serde(default, skip_serializing_if = "String::is_empty")]
326    pub input_cache_read: String,
327    /// Cached-input write pricing.
328    #[serde(default, skip_serializing_if = "String::is_empty")]
329    pub input_cache_write: String,
330    /// Discount as a multiplier (e.g. 0.5 = 50% off list).
331    #[serde(default)]
332    pub discount: f64,
333}
334
335/// A single endpoint from the ZDR endpoints listing.
336#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
337pub struct PublicEndpoint {
338    /// Endpoint display name.
339    #[serde(default)]
340    pub name: String,
341    /// Model id this endpoint serves.
342    #[serde(default)]
343    pub model_id: String,
344    /// Model display name.
345    #[serde(default)]
346    pub model_name: String,
347    /// Context window length, in tokens.
348    #[serde(default)]
349    pub context_length: f64,
350    /// Pricing information.
351    #[serde(default)]
352    pub pricing: PublicEndpointPricing,
353    /// Provider serving this endpoint.
354    #[serde(default)]
355    pub provider_name: String,
356    /// Optional provider-specific tag (e.g. region).
357    #[serde(default)]
358    pub tag: Option<String>,
359    /// Weight quantization label.
360    #[serde(default)]
361    pub quantization: Option<String>,
362    /// Maximum completion tokens supported, if advertised.
363    #[serde(default)]
364    pub max_completion_tokens: Option<f64>,
365    /// Maximum prompt tokens supported, if advertised.
366    #[serde(default)]
367    pub max_prompt_tokens: Option<f64>,
368    /// Provider-advertised supported parameter names.
369    #[serde(default)]
370    pub supported_parameters: Vec<String>,
371    /// Operational status (0 = healthy, non-zero = degraded).
372    #[serde(default)]
373    pub status: f64,
374    /// Rolling 30-minute uptime ratio.
375    #[serde(default)]
376    pub uptime_last_30m: Option<f64>,
377    /// Whether the endpoint reports implicit cache support.
378    #[serde(default)]
379    pub supports_implicit_caching: Option<bool>,
380    /// Recent latency percentiles.
381    #[serde(default)]
382    pub latency_last_30m: Option<PercentileStats>,
383    /// Recent throughput percentiles.
384    #[serde(default)]
385    pub throughput_last_30m: Option<PercentileStats>,
386}
387
388/// Response from `GET /endpoints/zdr`.
389#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
390pub struct ZdrEndpointsResponse {
391    /// The ZDR-certified endpoint rows.
392    #[serde(default)]
393    pub data: Vec<PublicEndpoint>,
394}