Skip to main content

gproxy_protocol/wire/openai/
video.rs

1//! OpenRouter-shaped video generation extension in the OpenAI wire family.
2//! Sources: design/protocol-spec.md section 7 and local OpenRouter Submit/Poll/
3//! Download video documents. Native* retains original OpenAI resource shapes;
4//! normalization/alias conversion is explicitly not performed by these DTOs.
5//! Native Video resource detail checked against openai-python commit
6//! e12b81d3bbf644ec7045e152d69bc4b68d69cd48, types/video.py (2026-09-13).
7use crate::connection::{HttpBody, MultipartPart};
8use crate::{Rest, WireRequest, WireResponse};
9use serde::{Deserialize, Serialize};
10use std::collections::BTreeMap;
11fn optional<'de, D, T>(d: D) -> Result<Option<T>, D::Error>
12where
13    D: serde::Deserializer<'de>,
14    T: Deserialize<'de>,
15{
16    T::deserialize(d).map(Some)
17}
18fn nullable<'de, D, T>(d: D) -> Result<Option<Option<T>>, D::Error>
19where
20    D: serde::Deserializer<'de>,
21    T: Deserialize<'de>,
22{
23    Option::<T>::deserialize(d).map(Some)
24}
25
26#[derive(
27    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
28)]
29#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
30#[derive(gproxy_protocol_macros::DeclaredFields)]
31pub struct CreateVideoRequestBody {
32    pub model: String,
33    #[serde(
34        default,
35        deserialize_with = "optional",
36        skip_serializing_if = "Option::is_none"
37    )]
38    pub prompt: Option<String>,
39    #[serde(
40        default,
41        deserialize_with = "optional",
42        skip_serializing_if = "Option::is_none"
43    )]
44    pub duration: Option<i64>,
45    #[serde(
46        default,
47        deserialize_with = "optional",
48        skip_serializing_if = "Option::is_none"
49    )]
50    pub aspect_ratio: Option<VideoAspectRatio>,
51    #[serde(
52        default,
53        deserialize_with = "optional",
54        skip_serializing_if = "Option::is_none"
55    )]
56    pub resolution: Option<VideoResolution>,
57    #[serde(
58        default,
59        deserialize_with = "optional",
60        skip_serializing_if = "Option::is_none"
61    )]
62    pub size: Option<String>,
63    #[serde(
64        default,
65        deserialize_with = "optional",
66        skip_serializing_if = "Option::is_none"
67    )]
68    pub seed: Option<i64>,
69    #[serde(
70        default,
71        deserialize_with = "optional",
72        skip_serializing_if = "Option::is_none"
73    )]
74    pub frame_images: Option<Vec<FrameImage>>,
75    #[serde(
76        default,
77        deserialize_with = "optional",
78        skip_serializing_if = "Option::is_none"
79    )]
80    pub input_references: Option<Vec<InputReference>>,
81    #[serde(
82        default,
83        deserialize_with = "optional",
84        skip_serializing_if = "Option::is_none"
85    )]
86    pub generate_audio: Option<bool>,
87    #[serde(
88        default,
89        deserialize_with = "optional",
90        skip_serializing_if = "Option::is_none"
91    )]
92    pub callback_url: Option<String>,
93    #[serde(
94        default,
95        deserialize_with = "optional",
96        skip_serializing_if = "Option::is_none"
97    )]
98    pub provider: Option<VideoProvider>,
99    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
100    pub rest: Rest,
101}
102
103#[derive(
104    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
105)]
106#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
107#[derive(gproxy_protocol_macros::DeclaredFields)]
108pub struct VideoGenerationResponseBody {
109    pub id: String,
110    pub polling_url: String,
111    pub status: VideoStatus,
112    #[serde(
113        default,
114        deserialize_with = "optional",
115        skip_serializing_if = "Option::is_none"
116    )]
117    pub error: Option<String>,
118    #[serde(
119        default,
120        deserialize_with = "optional",
121        skip_serializing_if = "Option::is_none"
122    )]
123    pub generation_id: Option<String>,
124    #[serde(
125        default,
126        deserialize_with = "optional",
127        skip_serializing_if = "Option::is_none"
128    )]
129    pub unsigned_urls: Option<Vec<String>>,
130    #[serde(
131        default,
132        deserialize_with = "optional",
133        skip_serializing_if = "Option::is_none"
134    )]
135    pub usage: Option<VideoUsage>,
136    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
137    pub rest: Rest,
138}
139
140#[derive(
141    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
142)]
143#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
144#[derive(gproxy_protocol_macros::DeclaredFields)]
145pub struct VideoUsage {
146    #[serde(
147        default,
148        deserialize_with = "nullable",
149        skip_serializing_if = "Option::is_none"
150    )]
151    pub cost: Option<Option<serde_json::Number>>,
152    #[serde(
153        default,
154        deserialize_with = "optional",
155        skip_serializing_if = "Option::is_none"
156    )]
157    pub is_byok: Option<bool>,
158    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
159    pub rest: Rest,
160}
161
162#[derive(
163    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
164)]
165#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
166/// provider.options is explicitly arbitrary per-provider JSON in the OpenRouter schema.
167/// Video provider configuration has no routing preferences; do not import rerank fields.
168#[derive(gproxy_protocol_macros::DeclaredFields)]
169pub struct VideoProvider {
170    #[serde(
171        default,
172        deserialize_with = "optional",
173        skip_serializing_if = "Option::is_none"
174    )]
175    pub options: Option<BTreeMap<String, Rest>>,
176    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
177    pub rest: Rest,
178}
179
180#[derive(
181    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
182)]
183#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
184#[derive(gproxy_protocol_macros::DeclaredFields)]
185pub struct ReferenceUrl {
186    pub url: String,
187    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
188    pub rest: Rest,
189}
190
191#[derive(
192    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
193)]
194#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
195#[derive(gproxy_protocol_macros::DeclaredFields)]
196pub struct FrameImage {
197    #[serde(rename = "type")]
198    pub type_: VideoImageType,
199    pub image_url: ReferenceUrl,
200    pub frame_type: FrameType,
201    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
202    pub rest: Rest,
203}
204
205#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
206#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
207#[derive(gproxy_protocol_macros::DeclaredFields)]
208pub enum VideoImageType {
209    #[serde(rename = "image_url")]
210    ImageUrl,
211}
212
213#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
214#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
215#[derive(gproxy_protocol_macros::DeclaredFields)]
216pub enum FrameType {
217    #[serde(rename = "first_frame")]
218    FirstFrame,
219    #[serde(rename = "last_frame")]
220    LastFrame,
221}
222
223#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
224#[serde(tag = "type")]
225#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
226#[derive(gproxy_protocol_macros::DeclaredFields)]
227pub enum InputReference {
228    #[serde(rename = "image_url")]
229    Image(InputImageReference),
230    #[serde(rename = "audio_url")]
231    Audio(InputAudioReference),
232    #[serde(rename = "video_url")]
233    Video(InputVideoReference),
234}
235
236#[derive(
237    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
238)]
239#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
240#[derive(gproxy_protocol_macros::DeclaredFields)]
241pub struct InputImageReference {
242    pub image_url: ReferenceUrl,
243    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
244    pub rest: Rest,
245}
246
247#[derive(
248    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
249)]
250#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
251#[derive(gproxy_protocol_macros::DeclaredFields)]
252pub struct InputAudioReference {
253    pub audio_url: ReferenceUrl,
254    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
255    pub rest: Rest,
256}
257
258#[derive(
259    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
260)]
261#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
262#[derive(gproxy_protocol_macros::DeclaredFields)]
263pub struct InputVideoReference {
264    pub video_url: ReferenceUrl,
265    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
266    pub rest: Rest,
267}
268
269#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
270#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
271#[derive(gproxy_protocol_macros::DeclaredFields)]
272pub enum VideoAspectRatio {
273    #[serde(rename = "16:9")]
274    R16x9,
275    #[serde(rename = "9:16")]
276    R9x16,
277    #[serde(rename = "1:1")]
278    R1x1,
279    #[serde(rename = "4:3")]
280    R4x3,
281    #[serde(rename = "3:4")]
282    R3x4,
283    #[serde(rename = "3:2")]
284    R3x2,
285    #[serde(rename = "2:3")]
286    R2x3,
287    #[serde(rename = "21:9")]
288    R21x9,
289    #[serde(rename = "9:21")]
290    R9x21,
291}
292
293#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
294#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
295#[derive(gproxy_protocol_macros::DeclaredFields)]
296pub enum VideoResolution {
297    #[serde(rename = "480p")]
298    P480,
299    #[serde(rename = "720p")]
300    P720,
301    #[serde(rename = "768p")]
302    P768,
303    #[serde(rename = "1080p")]
304    P1080,
305    #[serde(rename = "1K")]
306    K1,
307    #[serde(rename = "2K")]
308    K2,
309    #[serde(rename = "4K")]
310    K4,
311}
312
313#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
314#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
315#[derive(gproxy_protocol_macros::DeclaredFields)]
316pub enum VideoStatus {
317    #[serde(rename = "pending")]
318    Pending,
319    #[serde(rename = "in_progress")]
320    InProgress,
321    #[serde(rename = "completed")]
322    Completed,
323    #[serde(rename = "failed")]
324    Failed,
325    #[serde(rename = "cancelled")]
326    Cancelled,
327    #[serde(rename = "expired")]
328    Expired,
329}
330
331#[derive(
332    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
333)]
334#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
335#[derive(gproxy_protocol_macros::DeclaredFields)]
336pub struct RetrieveVideoPath {
337    #[serde(rename = "jobId")]
338    pub job_id: String,
339    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
340    pub rest: Rest,
341}
342
343#[derive(
344    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
345)]
346#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
347#[derive(gproxy_protocol_macros::DeclaredFields)]
348pub struct DownloadVideoQuery {
349    #[serde(
350        default,
351        deserialize_with = "nullable",
352        skip_serializing_if = "Option::is_none"
353    )]
354    pub index: Option<Option<i64>>,
355    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
356    pub rest: Rest,
357}
358
359pub type CreateVideoRequest = WireRequest<CreateVideoRequestBody>;
360pub type CreateVideoResponse = WireResponse<VideoGenerationResponseBody>;
361pub type RetrieveVideoRequest = WireRequest<()>;
362pub type RetrieveVideoResponse = WireResponse<VideoGenerationResponseBody>;
363pub type DownloadVideoRequest = WireRequest<()>;
364pub type DownloadVideoResponse = WireResponse<HttpBody>;
365
366#[derive(
367    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
368)]
369#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
370#[derive(gproxy_protocol_macros::DeclaredFields)]
371pub struct NativeCreateVideoRequestBody {
372    pub prompt: String,
373    #[serde(
374        default,
375        deserialize_with = "optional",
376        skip_serializing_if = "Option::is_none"
377    )]
378    pub input_reference: Option<NativeInputReference>,
379    #[serde(
380        default,
381        deserialize_with = "optional",
382        skip_serializing_if = "Option::is_none"
383    )]
384    pub model: Option<String>,
385    #[serde(
386        default,
387        deserialize_with = "optional",
388        skip_serializing_if = "Option::is_none"
389    )]
390    pub seconds: Option<NativeVideoSeconds>,
391    #[serde(
392        default,
393        deserialize_with = "optional",
394        skip_serializing_if = "Option::is_none"
395    )]
396    pub size: Option<NativeVideoSize>,
397    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
398    pub rest: Rest,
399}
400
401#[derive(Debug, gproxy_protocol_macros::WireBuilder)]
402#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
403#[derive(gproxy_protocol_macros::DeclaredFields)]
404pub struct NativeCreateVideoMultipartForm {
405    pub prompt: String,
406    pub input_reference: Option<MultipartPart>,
407    pub model: Option<String>,
408    pub seconds: Option<NativeVideoSeconds>,
409    pub size: Option<NativeVideoSize>,
410}
411
412#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
413#[serde(untagged)]
414#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
415#[derive(gproxy_protocol_macros::DeclaredFields)]
416pub enum NativeInputReference {
417    File(NativeFileReference),
418    Url(NativeUrlReference),
419}
420
421#[derive(
422    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
423)]
424#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
425#[derive(gproxy_protocol_macros::DeclaredFields)]
426pub struct NativeFileReference {
427    pub file_id: String,
428    #[serde(
429        default,
430        flatten,
431        deserialize_with = "file_extensions",
432        skip_serializing_if = "serde_json::Map::is_empty"
433    )]
434    pub rest: Rest,
435}
436
437#[derive(
438    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
439)]
440#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
441#[derive(gproxy_protocol_macros::DeclaredFields)]
442pub struct NativeUrlReference {
443    pub image_url: String,
444    #[serde(
445        default,
446        flatten,
447        deserialize_with = "url_extensions",
448        skip_serializing_if = "serde_json::Map::is_empty"
449    )]
450    pub rest: Rest,
451}
452
453fn file_extensions<'de, D: serde::Deserializer<'de>>(d: D) -> Result<Rest, D::Error> {
454    let rest = Rest::deserialize(d)?;
455    if rest.contains_key("image_url") {
456        return Err(serde::de::Error::custom(
457            "reference requires exactly one of file_id and image_url",
458        ));
459    }
460    Ok(rest)
461}
462fn url_extensions<'de, D: serde::Deserializer<'de>>(d: D) -> Result<Rest, D::Error> {
463    let rest = Rest::deserialize(d)?;
464    if rest.contains_key("file_id") {
465        return Err(serde::de::Error::custom(
466            "reference requires exactly one of file_id and image_url",
467        ));
468    }
469    Ok(rest)
470}
471
472#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
473#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
474#[derive(gproxy_protocol_macros::DeclaredFields)]
475pub enum NativeVideoSeconds {
476    #[serde(rename = "4")]
477    Four,
478    #[serde(rename = "8")]
479    Eight,
480    #[serde(rename = "12")]
481    Twelve,
482}
483
484#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
485#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
486#[derive(gproxy_protocol_macros::DeclaredFields)]
487pub enum NativeVideoSize {
488    #[serde(rename = "720x1280")]
489    Portrait720,
490    #[serde(rename = "1280x720")]
491    Landscape720,
492    #[serde(rename = "1024x1792")]
493    Portrait1024,
494    #[serde(rename = "1792x1024")]
495    Landscape1024,
496}
497
498#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
499#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
500#[derive(gproxy_protocol_macros::DeclaredFields)]
501pub enum NativeVideoStatus {
502    #[serde(rename = "queued")]
503    Queued,
504    #[serde(rename = "in_progress")]
505    InProgress,
506    #[serde(rename = "completed")]
507    Completed,
508    #[serde(rename = "failed")]
509    Failed,
510}
511
512#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
513#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
514#[derive(gproxy_protocol_macros::DeclaredFields)]
515pub enum NativeVideoObject {
516    #[serde(rename = "video")]
517    Video,
518}
519
520#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
521#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
522#[derive(gproxy_protocol_macros::DeclaredFields)]
523pub enum NativeVideoDeletedObject {
524    #[serde(rename = "video.deleted")]
525    VideoDeleted,
526}
527
528#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
529#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
530#[derive(gproxy_protocol_macros::DeclaredFields)]
531pub enum NativeVideoListOrder {
532    #[serde(rename = "asc")]
533    Asc,
534    #[serde(rename = "desc")]
535    Desc,
536}
537
538#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
539#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
540#[derive(gproxy_protocol_macros::DeclaredFields)]
541pub enum NativeVideoDownloadVariant {
542    #[serde(rename = "video")]
543    Video,
544    #[serde(rename = "thumbnail")]
545    Thumbnail,
546    #[serde(rename = "spritesheet")]
547    Spritesheet,
548}
549
550#[derive(
551    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
552)]
553#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
554#[derive(gproxy_protocol_macros::DeclaredFields)]
555pub struct NativeVideo {
556    pub id: String,
557    pub created_at: i64,
558    pub model: String,
559    pub object: NativeVideoObject,
560    pub progress: i64,
561    pub seconds: String,
562    pub size: NativeVideoSize,
563    pub status: NativeVideoStatus,
564    #[serde(
565        default,
566        deserialize_with = "nullable",
567        skip_serializing_if = "Option::is_none"
568    )]
569    pub completed_at: Option<Option<i64>>,
570    #[serde(
571        default,
572        deserialize_with = "nullable",
573        skip_serializing_if = "Option::is_none"
574    )]
575    pub error: Option<Option<NativeVideoError>>,
576    #[serde(
577        default,
578        deserialize_with = "nullable",
579        skip_serializing_if = "Option::is_none"
580    )]
581    pub expires_at: Option<Option<i64>>,
582    #[serde(
583        default,
584        deserialize_with = "nullable",
585        skip_serializing_if = "Option::is_none"
586    )]
587    pub prompt: Option<Option<String>>,
588    #[serde(
589        default,
590        deserialize_with = "nullable",
591        skip_serializing_if = "Option::is_none"
592    )]
593    pub remixed_from_video_id: Option<Option<String>>,
594    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
595    pub rest: Rest,
596}
597
598#[derive(
599    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
600)]
601#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
602#[derive(gproxy_protocol_macros::DeclaredFields)]
603pub struct NativeVideoError {
604    pub code: String,
605    pub message: String,
606    #[serde(
607        default,
608        deserialize_with = "nullable",
609        skip_serializing_if = "Option::is_none"
610    )]
611    pub misalignment: Option<Option<NativeVideoMisalignment>>,
612    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
613    pub rest: Rest,
614}
615
616#[derive(
617    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
618)]
619#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
620#[derive(gproxy_protocol_macros::DeclaredFields)]
621pub struct NativeVideoPath {
622    pub video_id: String,
623    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
624    pub rest: Rest,
625}
626
627#[derive(
628    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
629)]
630#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
631#[derive(gproxy_protocol_macros::DeclaredFields)]
632pub struct NativeListVideosQuery {
633    #[serde(
634        default,
635        deserialize_with = "optional",
636        skip_serializing_if = "Option::is_none"
637    )]
638    pub after: Option<String>,
639    #[serde(
640        default,
641        deserialize_with = "optional",
642        skip_serializing_if = "Option::is_none"
643    )]
644    pub limit: Option<i64>,
645    #[serde(
646        default,
647        deserialize_with = "optional",
648        skip_serializing_if = "Option::is_none"
649    )]
650    pub order: Option<NativeVideoListOrder>,
651    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
652    pub rest: Rest,
653}
654
655#[derive(
656    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
657)]
658#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
659#[derive(gproxy_protocol_macros::DeclaredFields)]
660pub struct NativeListVideosResponseBody {
661    pub data: Vec<NativeVideo>,
662    #[serde(
663        default,
664        deserialize_with = "nullable",
665        skip_serializing_if = "Option::is_none"
666    )]
667    pub has_more: Option<Option<bool>>,
668    #[serde(
669        default,
670        deserialize_with = "nullable",
671        skip_serializing_if = "Option::is_none"
672    )]
673    pub last_id: Option<Option<String>>,
674    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
675    pub rest: Rest,
676}
677
678#[derive(
679    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
680)]
681#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
682#[derive(gproxy_protocol_macros::DeclaredFields)]
683pub struct NativeDeleteVideoResponseBody {
684    pub id: String,
685    pub deleted: bool,
686    pub object: NativeVideoDeletedObject,
687    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
688    pub rest: Rest,
689}
690
691#[derive(
692    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
693)]
694#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
695#[derive(gproxy_protocol_macros::DeclaredFields)]
696pub struct NativeDownloadVideoQuery {
697    #[serde(
698        default,
699        deserialize_with = "optional",
700        skip_serializing_if = "Option::is_none"
701    )]
702    pub variant: Option<NativeVideoDownloadVariant>,
703    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
704    pub rest: Rest,
705}
706
707pub type NativeCreateVideoRequest = WireRequest<NativeCreateVideoRequestBody>;
708pub type NativeCreateVideoMultipartRequest = WireRequest<NativeCreateVideoMultipartForm>;
709pub type NativeRawCreateVideoRequest = WireRequest<crate::connection::Multipart>;
710pub type NativeCreateVideoResponse = WireResponse<NativeVideo>;
711pub type NativeRetrieveVideoRequest = WireRequest<()>;
712pub type NativeRetrieveVideoResponse = WireResponse<NativeVideo>;
713pub type NativeListVideosRequest = WireRequest<()>;
714pub type NativeListVideosResponse = WireResponse<NativeListVideosResponseBody>;
715pub type NativeDeleteVideoRequest = WireRequest<()>;
716pub type NativeDeleteVideoResponse = WireResponse<NativeDeleteVideoResponseBody>;
717pub type NativeDownloadVideoRequest = WireRequest<()>;
718pub type NativeDownloadVideoResponse = WireResponse<HttpBody>;
719
720/// video_create_error.py in the pinned SDK includes structured safety context.
721#[derive(
722    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
723)]
724#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
725#[derive(gproxy_protocol_macros::DeclaredFields)]
726pub struct NativeVideoMisalignment {
727    #[serde(
728        default,
729        deserialize_with = "nullable",
730        skip_serializing_if = "Option::is_none"
731    )]
732    pub detailed_explanation: Option<Option<String>>,
733    #[serde(
734        default,
735        deserialize_with = "nullable",
736        skip_serializing_if = "Option::is_none"
737    )]
738    pub error_type: Option<Option<String>>,
739    #[serde(
740        default,
741        deserialize_with = "nullable",
742        skip_serializing_if = "Option::is_none"
743    )]
744    pub steer: Option<Option<NativeVideoSteer>>,
745    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
746    pub rest: Rest,
747}
748#[derive(
749    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
750)]
751#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
752#[derive(gproxy_protocol_macros::DeclaredFields)]
753pub struct NativeVideoSteer {
754    pub message: String,
755    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
756    pub rest: Rest,
757}