From 26db6cdf324bb3f272646caa52d7ece9941dda65 Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Tue, 21 Apr 2026 21:37:35 -0400 Subject: [PATCH] api bindings --- .../image/edit/http_gpt_image_2_edit_image.rs | 47 +++++ .../src/requests/http/image/edit/mod.rs | 1 + .../text/http_gpt_image_2_text_to_image.rs | 41 ++++ .../src/requests/http/image/text/mod.rs | 1 + .../enqueue_gpt_image_2_edit_image_webhook.rs | 197 ++++++++++++++++++ .../src/requests/webhook/image/edit/mod.rs | 1 + ...queue_gpt_image_2_text_to_image_webhook.rs | 186 +++++++++++++++++ .../src/requests/webhook/image/text/mod.rs | 1 + 8 files changed, 475 insertions(+) create mode 100644 crates/api_clients/fal_client/src/requests/http/image/edit/http_gpt_image_2_edit_image.rs create mode 100644 crates/api_clients/fal_client/src/requests/http/image/text/http_gpt_image_2_text_to_image.rs create mode 100644 crates/api_clients/fal_client/src/requests/webhook/image/edit/enqueue_gpt_image_2_edit_image_webhook.rs create mode 100644 crates/api_clients/fal_client/src/requests/webhook/image/text/enqueue_gpt_image_2_text_to_image_webhook.rs diff --git a/crates/api_clients/fal_client/src/requests/http/image/edit/http_gpt_image_2_edit_image.rs b/crates/api_clients/fal_client/src/requests/http/image/edit/http_gpt_image_2_edit_image.rs new file mode 100644 index 0000000000..7718589c19 --- /dev/null +++ b/crates/api_clients/fal_client/src/requests/http/image/edit/http_gpt_image_2_edit_image.rs @@ -0,0 +1,47 @@ +use crate::requests::api::fal_request::FalRequest; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct GptImage2EditImageInput { + pub prompt: String, + + pub image_urls: Vec, + + /// The URL of the mask image to use for the generation. This indicates what part of the image to edit. + #[serde(skip_serializing_if = "Option::is_none")] + pub mask_url: Option, + + /// Possible enum values: square_hd, square, portrait_4_3, portrait_16_9, landscape_4_3, landscape_16_9, auto + #[serde(skip_serializing_if = "Option::is_none")] + pub image_size: Option, + + /// "low", "medium", "high" + #[serde(skip_serializing_if = "Option::is_none")] + pub quality: Option, + + /// 1 - 4 + /// Default: 1 + #[serde(skip_serializing_if = "Option::is_none")] + pub num_images: Option, + + /// "jpeg", "png", "webp" + /// Default: "png" + #[serde(skip_serializing_if = "Option::is_none")] + pub output_format: Option, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct GptImage2EditImageFile { + pub url: String, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct GptImage2EditImageOutput { + pub images: Vec, +} + +pub fn gpt_image_2_edit_image( + params: GptImage2EditImageInput, +) -> FalRequest { + FalRequest::new("fal-ai/gpt-image-2/edit", params) +} diff --git a/crates/api_clients/fal_client/src/requests/http/image/edit/mod.rs b/crates/api_clients/fal_client/src/requests/http/image/edit/mod.rs index 5c90940293..09639cae82 100644 --- a/crates/api_clients/fal_client/src/requests/http/image/edit/mod.rs +++ b/crates/api_clients/fal_client/src/requests/http/image/edit/mod.rs @@ -5,6 +5,7 @@ pub mod http_gemini_25_flash_edit; pub mod http_gpt_image_1_edit_image; pub mod http_gpt_image_1_non_byok_edit_image; pub mod http_gpt_image_1p5_edit_image; +pub mod http_gpt_image_2_edit_image; pub mod http_nano_banana_2_edit_image; pub mod http_nano_banana_pro_edit_image; pub mod http_qwen_image_edit; diff --git a/crates/api_clients/fal_client/src/requests/http/image/text/http_gpt_image_2_text_to_image.rs b/crates/api_clients/fal_client/src/requests/http/image/text/http_gpt_image_2_text_to_image.rs new file mode 100644 index 0000000000..d178735931 --- /dev/null +++ b/crates/api_clients/fal_client/src/requests/http/image/text/http_gpt_image_2_text_to_image.rs @@ -0,0 +1,41 @@ +use crate::requests::api::fal_request::FalRequest; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct GptImage2TextToImageInput { + pub prompt: String, + + /// "1024x768", "1024x1024", "1024x1536", "1920x1080", "2560x1440", "3840x2160" + #[serde(skip_serializing_if = "Option::is_none")] + pub image_size: Option, + + /// "low", "medium", "high" + #[serde(skip_serializing_if = "Option::is_none")] + pub quality: Option, + + /// 1 - 4 + /// Default: 1 + #[serde(skip_serializing_if = "Option::is_none")] + pub num_images: Option, + + /// "jpeg", "png", "webp" + /// Default: "png" + #[serde(skip_serializing_if = "Option::is_none")] + pub output_format: Option, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct GptImage2TextToImageFile { + pub url: String, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct GptImage2TextToImageOutput { + pub images: Vec, +} + +pub fn gpt_image_2_text_to_image( + params: GptImage2TextToImageInput, +) -> FalRequest { + FalRequest::new("fal-ai/gpt-image-2", params) +} diff --git a/crates/api_clients/fal_client/src/requests/http/image/text/mod.rs b/crates/api_clients/fal_client/src/requests/http/image/text/mod.rs index 117dd19289..4b3edbfd1e 100644 --- a/crates/api_clients/fal_client/src/requests/http/image/text/mod.rs +++ b/crates/api_clients/fal_client/src/requests/http/image/text/mod.rs @@ -6,6 +6,7 @@ pub mod http_gemini_25_flash_text_to_image; pub mod http_gpt_image_1_non_byok_text_to_image; pub mod http_gpt_image_1_text_to_image; pub mod http_gpt_image_1p5_text_to_image; +pub mod http_gpt_image_2_text_to_image; pub mod http_nano_banana_2_text_to_image; pub mod http_nano_banana_pro_text_to_image; pub mod http_seedream_4_text_to_image; diff --git a/crates/api_clients/fal_client/src/requests/webhook/image/edit/enqueue_gpt_image_2_edit_image_webhook.rs b/crates/api_clients/fal_client/src/requests/webhook/image/edit/enqueue_gpt_image_2_edit_image_webhook.rs new file mode 100644 index 0000000000..ccdfa38835 --- /dev/null +++ b/crates/api_clients/fal_client/src/requests/webhook/image/edit/enqueue_gpt_image_2_edit_image_webhook.rs @@ -0,0 +1,197 @@ +use crate::creds::fal_api_key::FalApiKey; +use crate::error::classify_fal_error::classify_fal_error; +use crate::error::fal_error_plus::FalErrorPlus; +use crate::requests::traits::fal_request_cost_calculator_trait::{FalRequestCostCalculator, UsdCents}; +use crate::requests::http::image::edit::http_gpt_image_2_edit_image::{gpt_image_2_edit_image, GptImage2EditImageInput}; +use crate::requests::api::webhook_response::WebhookResponse; +use reqwest::IntoUrl; + +pub struct EnqueueGptImage2EditImageArgs<'a, R: IntoUrl> { + // Request required + pub prompt: &'a str, + pub image_urls: Vec, + pub num_images: EnqueueGptImage2EditImageNumImages, + + // Optional args + pub mask_url: Option, + pub image_size: Option, + pub quality: Option, + pub output_format: Option, + + // Fulfillment + pub webhook_url: R, + pub api_key: &'a FalApiKey, +} + +#[derive(Copy, Clone, Debug)] +pub enum EnqueueGptImage2EditImageNumImages { + One, + Two, + Three, + Four, +} + +#[derive(Copy, Clone, Debug)] +pub enum EnqueueGptImage2EditImageSize { + /// 1024x768 + Landscape4x3, + /// 1024x1024 + Square, + /// 1024x1536 + Portrait, + /// 1920x1080 + Landscape16x9, + /// 2560x1440 + Qhd, + /// 3840x2160 + Uhd4k, +} + +#[derive(Copy, Clone, Debug)] +pub enum EnqueueGptImage2EditImageQuality { + Low, + Medium, + High, +} + +#[derive(Copy, Clone, Debug)] +pub enum EnqueueGptImage2EditImageOutputFormat { + Jpeg, + Png, + Webp, +} + + +impl FalRequestCostCalculator for EnqueueGptImage2EditImageArgs<'_, U> { + fn calculate_cost_in_cents(&self) -> UsdCents { + // Cost table (per image): + // 1024x768: low=$0.01, medium=$0.04, high=$0.15 + // 1024x1024: low=$0.01, medium=$0.06, high=$0.22 + // 1024x1536: low=$0.01, medium=$0.05, high=$0.17 + // 1920x1080: low=$0.01, medium=$0.04, high=$0.16 + // 2560x1440: low=$0.01, medium=$0.06, high=$0.23 + // 3840x2160: low=$0.02, medium=$0.11, high=$0.41 + let use_quality = self.quality.unwrap_or(EnqueueGptImage2EditImageQuality::High); + let use_size = self.image_size.unwrap_or(EnqueueGptImage2EditImageSize::Square); + let base_cost = match (use_quality, use_size) { + (EnqueueGptImage2EditImageQuality::Low, EnqueueGptImage2EditImageSize::Uhd4k) => 2, + (EnqueueGptImage2EditImageQuality::Low, _) => 1, + (EnqueueGptImage2EditImageQuality::Medium, EnqueueGptImage2EditImageSize::Landscape4x3) => 4, + (EnqueueGptImage2EditImageQuality::Medium, EnqueueGptImage2EditImageSize::Square) => 6, + (EnqueueGptImage2EditImageQuality::Medium, EnqueueGptImage2EditImageSize::Portrait) => 5, + (EnqueueGptImage2EditImageQuality::Medium, EnqueueGptImage2EditImageSize::Landscape16x9) => 4, + (EnqueueGptImage2EditImageQuality::Medium, EnqueueGptImage2EditImageSize::Qhd) => 6, + (EnqueueGptImage2EditImageQuality::Medium, EnqueueGptImage2EditImageSize::Uhd4k) => 11, + (EnqueueGptImage2EditImageQuality::High, EnqueueGptImage2EditImageSize::Landscape4x3) => 15, + (EnqueueGptImage2EditImageQuality::High, EnqueueGptImage2EditImageSize::Square) => 22, + (EnqueueGptImage2EditImageQuality::High, EnqueueGptImage2EditImageSize::Portrait) => 17, + (EnqueueGptImage2EditImageQuality::High, EnqueueGptImage2EditImageSize::Landscape16x9) => 16, + (EnqueueGptImage2EditImageQuality::High, EnqueueGptImage2EditImageSize::Qhd) => 23, + (EnqueueGptImage2EditImageQuality::High, EnqueueGptImage2EditImageSize::Uhd4k) => 41, + }; + let cost = match self.num_images { + EnqueueGptImage2EditImageNumImages::One => base_cost, + EnqueueGptImage2EditImageNumImages::Two => base_cost * 2, + EnqueueGptImage2EditImageNumImages::Three => base_cost * 3, + EnqueueGptImage2EditImageNumImages::Four => base_cost * 4, + }; + cost as UsdCents + } +} + + +pub async fn enqueue_gpt_image_2_edit_image_webhook( + args: EnqueueGptImage2EditImageArgs<'_, R> +) -> Result { + + let num_images = match args.num_images { + EnqueueGptImage2EditImageNumImages::One => 1, + EnqueueGptImage2EditImageNumImages::Two => 2, + EnqueueGptImage2EditImageNumImages::Three => 3, + EnqueueGptImage2EditImageNumImages::Four => 4, + }; + + let image_size = args.image_size + .map(|s| match s { + EnqueueGptImage2EditImageSize::Landscape4x3 => "1024x768", + EnqueueGptImage2EditImageSize::Square => "1024x1024", + EnqueueGptImage2EditImageSize::Portrait => "1024x1536", + EnqueueGptImage2EditImageSize::Landscape16x9 => "1920x1080", + EnqueueGptImage2EditImageSize::Qhd => "2560x1440", + EnqueueGptImage2EditImageSize::Uhd4k => "3840x2160", + }) + .map(|resolution| resolution.to_string()); + + let quality = args.quality + .map(|s| match s { + EnqueueGptImage2EditImageQuality::Low => "low", + EnqueueGptImage2EditImageQuality::Medium => "medium", + EnqueueGptImage2EditImageQuality::High => "high", + }) + .map(|quality| quality.to_string()); + + let output_format = args.output_format + .map(|s| match s { + EnqueueGptImage2EditImageOutputFormat::Jpeg => "jpeg", + EnqueueGptImage2EditImageOutputFormat::Png => "png", + EnqueueGptImage2EditImageOutputFormat::Webp => "webp", + }) + .map(|format| format.to_string()) + .unwrap_or_else(|| "png".to_string()); + + let request = GptImage2EditImageInput { + prompt: args.prompt.to_string(), + image_urls: args.image_urls, + num_images: Some(num_images), + output_format: Some(output_format), + // Optionals + mask_url: args.mask_url, + image_size, + quality, + }; + + let result = gpt_image_2_edit_image(request) + .with_api_key(&args.api_key.0) + .queue_webhook(args.webhook_url) + .await; + + result.map_err(|err| classify_fal_error(err)) +} + +#[cfg(test)] +mod tests { + use crate::creds::fal_api_key::FalApiKey; + use crate::requests::webhook::image::edit::enqueue_gpt_image_2_edit_image_webhook::{enqueue_gpt_image_2_edit_image_webhook, EnqueueGptImage2EditImageArgs, EnqueueGptImage2EditImageNumImages}; + use errors::AnyhowResult; + use std::fs::read_to_string; + use test_data::web::image_urls::{ERNEST_SCARED_STUPID_IMAGE_URL, GHOST_IMAGE_URL, TREX_SKELETON_IMAGE_URL}; + + #[tokio::test] + #[ignore] + async fn test() -> AnyhowResult<()> { + // XXX: Don't commit secrets! + let secret = read_to_string("/Users/bt/Artcraft/credentials/fal_api_key.txt")?; + + let api_key = FalApiKey::from_str(&secret); + + let args = EnqueueGptImage2EditImageArgs { + image_urls: vec![ + GHOST_IMAGE_URL.to_string(), + TREX_SKELETON_IMAGE_URL.to_string(), + ERNEST_SCARED_STUPID_IMAGE_URL.to_string(), + ], + prompt: "add the ghost and scared man to the image of the t-rex skeleton, make it look spooky but friendly", + num_images: EnqueueGptImage2EditImageNumImages::Two, + mask_url: None, + image_size: None, + quality: None, + api_key: &api_key, + webhook_url: "https://example.com/webhook", + output_format: None, + }; + + let result = enqueue_gpt_image_2_edit_image_webhook(args).await?; + + Ok(()) + } +} diff --git a/crates/api_clients/fal_client/src/requests/webhook/image/edit/mod.rs b/crates/api_clients/fal_client/src/requests/webhook/image/edit/mod.rs index 1086e70923..34016527f9 100644 --- a/crates/api_clients/fal_client/src/requests/webhook/image/edit/mod.rs +++ b/crates/api_clients/fal_client/src/requests/webhook/image/edit/mod.rs @@ -9,6 +9,7 @@ pub mod enqueue_gemini_25_flash_edit_webhook; pub mod enqueue_gpt_image_1_byok_edit_image_webhook; pub mod enqueue_gpt_image_1_edit_image_webhook; pub mod enqueue_gpt_image_1p5_edit_image_webhook; +pub mod enqueue_gpt_image_2_edit_image_webhook; pub mod enqueue_nano_banana_pro_edit_image_webhook; pub mod enqueue_qwen_image_edit_webhook; pub mod enqueue_seededit_v3_edit_webhook; \ No newline at end of file diff --git a/crates/api_clients/fal_client/src/requests/webhook/image/text/enqueue_gpt_image_2_text_to_image_webhook.rs b/crates/api_clients/fal_client/src/requests/webhook/image/text/enqueue_gpt_image_2_text_to_image_webhook.rs new file mode 100644 index 0000000000..0324d575b7 --- /dev/null +++ b/crates/api_clients/fal_client/src/requests/webhook/image/text/enqueue_gpt_image_2_text_to_image_webhook.rs @@ -0,0 +1,186 @@ +use crate::creds::fal_api_key::FalApiKey; +use crate::error::classify_fal_error::classify_fal_error; +use crate::error::fal_error_plus::FalErrorPlus; +use crate::requests::traits::fal_request_cost_calculator_trait::{FalRequestCostCalculator, UsdCents}; +use crate::requests::http::image::text::http_gpt_image_2_text_to_image::{gpt_image_2_text_to_image, GptImage2TextToImageInput}; +use crate::requests::api::webhook_response::WebhookResponse; +use reqwest::IntoUrl; + +pub struct EnqueueGptImage2TextToImageArgs<'a, R: IntoUrl> { + // Request required + pub prompt: &'a str, + pub num_images: EnqueueGptImage2TextToImageNumImages, + + // Optional args + pub image_size: Option, + pub quality: Option, + pub output_format: Option, + + // Fulfillment + pub webhook_url: R, + pub api_key: &'a FalApiKey, +} + +#[derive(Copy, Clone, Debug)] +pub enum EnqueueGptImage2TextToImageNumImages { + One, + Two, + Three, + Four, +} + +#[derive(Copy, Clone, Debug)] +pub enum EnqueueGptImage2TextToImageSize { + /// 1024x768 + Landscape4x3, + /// 1024x1024 + Square, + /// 1024x1536 + Portrait, + /// 1920x1080 + Landscape16x9, + /// 2560x1440 + Qhd, + /// 3840x2160 + Uhd4k, +} + +#[derive(Copy, Clone, Debug)] +pub enum EnqueueGptImage2TextToImageQuality { + Low, + Medium, + High, +} + +#[derive(Copy, Clone, Debug)] +pub enum EnqueueGptImage2TextToImageOutputFormat { + Jpeg, + Png, + Webp, +} + + +impl FalRequestCostCalculator for EnqueueGptImage2TextToImageArgs<'_, U> { + fn calculate_cost_in_cents(&self) -> UsdCents { + // Cost table (per image): + // 1024x768: low=$0.01, medium=$0.04, high=$0.15 + // 1024x1024: low=$0.01, medium=$0.06, high=$0.22 + // 1024x1536: low=$0.01, medium=$0.05, high=$0.17 + // 1920x1080: low=$0.01, medium=$0.04, high=$0.16 + // 2560x1440: low=$0.01, medium=$0.06, high=$0.23 + // 3840x2160: low=$0.02, medium=$0.11, high=$0.41 + let use_quality = self.quality.unwrap_or(EnqueueGptImage2TextToImageQuality::High); + let use_size = self.image_size.unwrap_or(EnqueueGptImage2TextToImageSize::Square); + let base_cost = match (use_quality, use_size) { + (EnqueueGptImage2TextToImageQuality::Low, EnqueueGptImage2TextToImageSize::Uhd4k) => 2, + (EnqueueGptImage2TextToImageQuality::Low, _) => 1, + (EnqueueGptImage2TextToImageQuality::Medium, EnqueueGptImage2TextToImageSize::Landscape4x3) => 4, + (EnqueueGptImage2TextToImageQuality::Medium, EnqueueGptImage2TextToImageSize::Square) => 6, + (EnqueueGptImage2TextToImageQuality::Medium, EnqueueGptImage2TextToImageSize::Portrait) => 5, + (EnqueueGptImage2TextToImageQuality::Medium, EnqueueGptImage2TextToImageSize::Landscape16x9) => 4, + (EnqueueGptImage2TextToImageQuality::Medium, EnqueueGptImage2TextToImageSize::Qhd) => 6, + (EnqueueGptImage2TextToImageQuality::Medium, EnqueueGptImage2TextToImageSize::Uhd4k) => 11, + (EnqueueGptImage2TextToImageQuality::High, EnqueueGptImage2TextToImageSize::Landscape4x3) => 15, + (EnqueueGptImage2TextToImageQuality::High, EnqueueGptImage2TextToImageSize::Square) => 22, + (EnqueueGptImage2TextToImageQuality::High, EnqueueGptImage2TextToImageSize::Portrait) => 17, + (EnqueueGptImage2TextToImageQuality::High, EnqueueGptImage2TextToImageSize::Landscape16x9) => 16, + (EnqueueGptImage2TextToImageQuality::High, EnqueueGptImage2TextToImageSize::Qhd) => 23, + (EnqueueGptImage2TextToImageQuality::High, EnqueueGptImage2TextToImageSize::Uhd4k) => 41, + }; + let cost = match self.num_images { + EnqueueGptImage2TextToImageNumImages::One => base_cost, + EnqueueGptImage2TextToImageNumImages::Two => base_cost * 2, + EnqueueGptImage2TextToImageNumImages::Three => base_cost * 3, + EnqueueGptImage2TextToImageNumImages::Four => base_cost * 4, + }; + cost as UsdCents + } +} + + +pub async fn enqueue_gpt_image_2_text_to_image_webhook( + args: EnqueueGptImage2TextToImageArgs<'_, R> +) -> Result { + + let num_images = match args.num_images { + EnqueueGptImage2TextToImageNumImages::One => 1, + EnqueueGptImage2TextToImageNumImages::Two => 2, + EnqueueGptImage2TextToImageNumImages::Three => 3, + EnqueueGptImage2TextToImageNumImages::Four => 4, + }; + + let image_size = args.image_size + .map(|s| match s { + EnqueueGptImage2TextToImageSize::Landscape4x3 => "1024x768", + EnqueueGptImage2TextToImageSize::Square => "1024x1024", + EnqueueGptImage2TextToImageSize::Portrait => "1024x1536", + EnqueueGptImage2TextToImageSize::Landscape16x9 => "1920x1080", + EnqueueGptImage2TextToImageSize::Qhd => "2560x1440", + EnqueueGptImage2TextToImageSize::Uhd4k => "3840x2160", + }) + .map(|resolution| resolution.to_string()); + + let quality = args.quality + .map(|s| match s { + EnqueueGptImage2TextToImageQuality::Low => "low", + EnqueueGptImage2TextToImageQuality::Medium => "medium", + EnqueueGptImage2TextToImageQuality::High => "high", + }) + .map(|quality| quality.to_string()); + + let output_format = args.output_format + .map(|s| match s { + EnqueueGptImage2TextToImageOutputFormat::Jpeg => "jpeg", + EnqueueGptImage2TextToImageOutputFormat::Png => "png", + EnqueueGptImage2TextToImageOutputFormat::Webp => "webp", + }) + .map(|format| format.to_string()) + .unwrap_or_else(|| "png".to_string()); + + let request = GptImage2TextToImageInput { + prompt: args.prompt.to_string(), + num_images: Some(num_images), + output_format: Some(output_format), + // Optionals + image_size, + quality, + }; + + let result = gpt_image_2_text_to_image(request) + .with_api_key(&args.api_key.0) + .queue_webhook(args.webhook_url) + .await; + + result.map_err(|err| classify_fal_error(err)) +} + +#[cfg(test)] +mod tests { + use crate::creds::fal_api_key::FalApiKey; + use crate::requests::webhook::image::text::enqueue_gpt_image_2_text_to_image_webhook::{enqueue_gpt_image_2_text_to_image_webhook, EnqueueGptImage2TextToImageArgs, EnqueueGptImage2TextToImageNumImages}; + use errors::AnyhowResult; + use std::fs::read_to_string; + + #[tokio::test] + #[ignore] + async fn test() -> AnyhowResult<()> { + // XXX: Don't commit secrets! + let secret = read_to_string("/Users/bt/Artcraft/credentials/fal_api_key.txt")?; + + let api_key = FalApiKey::from_str(&secret); + + let args = EnqueueGptImage2TextToImageArgs { + prompt: "an anime girl riding on the back of a t-rex", + num_images: EnqueueGptImage2TextToImageNumImages::Two, + image_size: None, + quality: None, + api_key: &api_key, + webhook_url: "https://example.com/webhook", + output_format: None, + }; + + let result = enqueue_gpt_image_2_text_to_image_webhook(args).await?; + + Ok(()) + } +} diff --git a/crates/api_clients/fal_client/src/requests/webhook/image/text/mod.rs b/crates/api_clients/fal_client/src/requests/webhook/image/text/mod.rs index 6bfa064228..3199122984 100644 --- a/crates/api_clients/fal_client/src/requests/webhook/image/text/mod.rs +++ b/crates/api_clients/fal_client/src/requests/webhook/image/text/mod.rs @@ -10,4 +10,5 @@ pub mod enqueue_gemini_25_flash_text_to_image_webhook; pub mod enqueue_gpt_image_1_byok_text_to_image_webhook; pub mod enqueue_gpt_image_1_text_to_image_webhook; pub mod enqueue_gpt_image_1p5_text_to_image_webhook; +pub mod enqueue_gpt_image_2_text_to_image_webhook; pub mod enqueue_nano_banana_pro_text_to_image_webhook; \ No newline at end of file