From 0e13593e38bbf7d0120182d390727593ecefb189 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Mon, 6 Jul 2026 20:01:39 +0000
Subject: [PATCH 1/2] feat(api): add ad_localization recipe
Add POST /v1/recipes/ad_localization for localizing ad images by target
language (referenceImage + targetLanguage).
---
.stats.yml | 8 +-
api.md | 2 +
src/runwayml/resources/recipes.py | 162 ++++++++++++++++++
src/runwayml/types/__init__.py | 2 +
.../types/recipe_ad_localization_params.py | 68 ++++++++
.../types/recipe_ad_localization_response.py | 10 ++
tests/api_resources/test_recipes.py | 75 ++++++++
7 files changed, 323 insertions(+), 4 deletions(-)
create mode 100644 src/runwayml/types/recipe_ad_localization_params.py
create mode 100644 src/runwayml/types/recipe_ad_localization_response.py
diff --git a/.stats.yml b/.stats.yml
index f6fb8cf..b1f4800 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 50
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runwayml/runwayml-caa255c8f1c6fd2b54d331eeacc13de517b8dbaba491ef94745d107798b5eb7a.yml
-openapi_spec_hash: d9f7b43604b06f389e2fc45376d0a519
-config_hash: 955a0e451964a44778c5c0f54ca1c994
+configured_endpoints: 51
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runwayml/runwayml-d934e6804620f70a9a7d88bb3acf27146b57860ed56691e390e46027b3c04d4a.yml
+openapi_spec_hash: 132fc1ce816bcfd680a239dc1ed58c8e
+config_hash: 7caf94f26186e1ee432efcaa0b590bab
diff --git a/api.md b/api.md
index 857cab3..5b8a55f 100644
--- a/api.md
+++ b/api.md
@@ -253,6 +253,7 @@ Types:
```python
from runwayml.types import (
+ RecipeAdLocalizationResponse,
RecipeMarketingStockImageResponse,
RecipeMultiShotVideoResponse,
RecipeProductAdResponse,
@@ -264,6 +265,7 @@ from runwayml.types import (
Methods:
+- client.recipes.ad_localization(\*\*params) -> RecipeAdLocalizationResponse
- client.recipes.marketing_stock_image(\*\*params) -> RecipeMarketingStockImageResponse
- client.recipes.multi_shot_video(\*\*params) -> RecipeMultiShotVideoResponse
- client.recipes.product_ad(\*\*params) -> RecipeProductAdResponse
diff --git a/src/runwayml/resources/recipes.py b/src/runwayml/resources/recipes.py
index be41774..3e751d2 100644
--- a/src/runwayml/resources/recipes.py
+++ b/src/runwayml/resources/recipes.py
@@ -18,6 +18,7 @@
recipe_product_ad_params,
recipe_product_ugc_params,
recipe_product_swap_params,
+ recipe_ad_localization_params,
recipe_multi_shot_video_params,
recipe_marketing_stock_image_params,
recipe_product_campaign_image_params,
@@ -36,6 +37,7 @@
from ..types.recipe_product_ad_response import RecipeProductAdResponse
from ..types.recipe_product_ugc_response import RecipeProductUgcResponse
from ..types.recipe_product_swap_response import RecipeProductSwapResponse
+from ..types.recipe_ad_localization_response import RecipeAdLocalizationResponse
from ..types.recipe_multi_shot_video_response import RecipeMultiShotVideoResponse
from ..types.recipe_marketing_stock_image_response import RecipeMarketingStockImageResponse
from ..types.recipe_product_campaign_image_response import RecipeProductCampaignImageResponse
@@ -63,6 +65,80 @@ def with_streaming_response(self) -> RecipesResourceWithStreamingResponse:
"""
return RecipesResourceWithStreamingResponse(self)
+ def ad_localization(
+ self,
+ *,
+ reference_image: recipe_ad_localization_params.ReferenceImage,
+ target_language: Literal[
+ "ar",
+ "zh",
+ "zh-Hant",
+ "nl",
+ "en",
+ "fr",
+ "de",
+ "hi",
+ "id",
+ "it",
+ "ja",
+ "ko",
+ "pl",
+ "pt",
+ "ru",
+ "es",
+ "sv",
+ "th",
+ "tr",
+ "uk",
+ "vi",
+ "el",
+ ],
+ version: Literal["2026-06", "unsafe-latest"],
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> NewTaskCreatedResponse:
+ """
+ Localize an existing ad image for a target language, preserving visual creative
+ while adapting on-screen messaging.
+
+ Args:
+ reference_image: Reference ad image to localize. See [our docs](/assets/inputs#images) on image
+ inputs.
+
+ target_language: Target language for the localized ad. Use ISO-style codes (e.g. "ja" for
+ Japanese, "es" for Spanish).
+
+ version: Workflow version. Use a dated version (e.g. "2026-06") to pin behavior, or
+ "unsafe-latest" to track the newest stable version (may break without notice).
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ return self._post(
+ "/v1/recipes/ad_localization",
+ body=maybe_transform(
+ {
+ "reference_image": reference_image,
+ "target_language": target_language,
+ "version": version,
+ },
+ recipe_ad_localization_params.RecipeAdLocalizationParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=create_waitable_resource(RecipeAdLocalizationResponse, self._client),
+ )
+
def marketing_stock_image(
self,
*,
@@ -564,6 +640,80 @@ def with_streaming_response(self) -> AsyncRecipesResourceWithStreamingResponse:
"""
return AsyncRecipesResourceWithStreamingResponse(self)
+ async def ad_localization(
+ self,
+ *,
+ reference_image: recipe_ad_localization_params.ReferenceImage,
+ target_language: Literal[
+ "ar",
+ "zh",
+ "zh-Hant",
+ "nl",
+ "en",
+ "fr",
+ "de",
+ "hi",
+ "id",
+ "it",
+ "ja",
+ "ko",
+ "pl",
+ "pt",
+ "ru",
+ "es",
+ "sv",
+ "th",
+ "tr",
+ "uk",
+ "vi",
+ "el",
+ ],
+ version: Literal["2026-06", "unsafe-latest"],
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> AsyncNewTaskCreatedResponse:
+ """
+ Localize an existing ad image for a target language, preserving visual creative
+ while adapting on-screen messaging.
+
+ Args:
+ reference_image: Reference ad image to localize. See [our docs](/assets/inputs#images) on image
+ inputs.
+
+ target_language: Target language for the localized ad. Use ISO-style codes (e.g. "ja" for
+ Japanese, "es" for Spanish).
+
+ version: Workflow version. Use a dated version (e.g. "2026-06") to pin behavior, or
+ "unsafe-latest" to track the newest stable version (may break without notice).
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ return await self._post(
+ "/v1/recipes/ad_localization",
+ body=await async_maybe_transform(
+ {
+ "reference_image": reference_image,
+ "target_language": target_language,
+ "version": version,
+ },
+ recipe_ad_localization_params.RecipeAdLocalizationParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=create_async_waitable_resource(RecipeAdLocalizationResponse, self._client),
+ )
+
async def marketing_stock_image(
self,
*,
@@ -1049,6 +1199,9 @@ class RecipesResourceWithRawResponse:
def __init__(self, recipes: RecipesResource) -> None:
self._recipes = recipes
+ self.ad_localization = to_raw_response_wrapper(
+ recipes.ad_localization,
+ )
self.marketing_stock_image = to_raw_response_wrapper(
recipes.marketing_stock_image,
)
@@ -1073,6 +1226,9 @@ class AsyncRecipesResourceWithRawResponse:
def __init__(self, recipes: AsyncRecipesResource) -> None:
self._recipes = recipes
+ self.ad_localization = async_to_raw_response_wrapper(
+ recipes.ad_localization,
+ )
self.marketing_stock_image = async_to_raw_response_wrapper(
recipes.marketing_stock_image,
)
@@ -1097,6 +1253,9 @@ class RecipesResourceWithStreamingResponse:
def __init__(self, recipes: RecipesResource) -> None:
self._recipes = recipes
+ self.ad_localization = to_streamed_response_wrapper(
+ recipes.ad_localization,
+ )
self.marketing_stock_image = to_streamed_response_wrapper(
recipes.marketing_stock_image,
)
@@ -1121,6 +1280,9 @@ class AsyncRecipesResourceWithStreamingResponse:
def __init__(self, recipes: AsyncRecipesResource) -> None:
self._recipes = recipes
+ self.ad_localization = async_to_streamed_response_wrapper(
+ recipes.ad_localization,
+ )
self.marketing_stock_image = async_to_streamed_response_wrapper(
recipes.marketing_stock_image,
)
diff --git a/src/runwayml/types/__init__.py b/src/runwayml/types/__init__.py
index fbb5637..05d793a 100644
--- a/src/runwayml/types/__init__.py
+++ b/src/runwayml/types/__init__.py
@@ -50,6 +50,7 @@
from .text_to_speech_create_params import TextToSpeechCreateParams as TextToSpeechCreateParams
from .video_to_video_create_params import VideoToVideoCreateParams as VideoToVideoCreateParams
from .image_upscale_create_response import ImageUpscaleCreateResponse as ImageUpscaleCreateResponse
+from .recipe_ad_localization_params import RecipeAdLocalizationParams as RecipeAdLocalizationParams
from .text_to_image_create_response import TextToImageCreateResponse as TextToImageCreateResponse
from .text_to_video_create_response import TextToVideoCreateResponse as TextToVideoCreateResponse
from .video_upscale_create_response import VideoUpscaleCreateResponse as VideoUpscaleCreateResponse
@@ -63,6 +64,7 @@
from .text_to_speech_create_response import TextToSpeechCreateResponse as TextToSpeechCreateResponse
from .video_to_video_create_response import VideoToVideoCreateResponse as VideoToVideoCreateResponse
from .avatar_conversation_list_params import AvatarConversationListParams as AvatarConversationListParams
+from .recipe_ad_localization_response import RecipeAdLocalizationResponse as RecipeAdLocalizationResponse
from .voice_isolation_create_response import VoiceIsolationCreateResponse as VoiceIsolationCreateResponse
from .realtime_session_create_response import RealtimeSessionCreateResponse as RealtimeSessionCreateResponse
from .recipe_multi_shot_video_response import RecipeMultiShotVideoResponse as RecipeMultiShotVideoResponse
diff --git a/src/runwayml/types/recipe_ad_localization_params.py b/src/runwayml/types/recipe_ad_localization_params.py
new file mode 100644
index 0000000..da31daa
--- /dev/null
+++ b/src/runwayml/types/recipe_ad_localization_params.py
@@ -0,0 +1,68 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, Required, Annotated, TypedDict
+
+from .._utils import PropertyInfo
+
+__all__ = ["RecipeAdLocalizationParams", "ReferenceImage"]
+
+
+class RecipeAdLocalizationParams(TypedDict, total=False):
+ reference_image: Required[Annotated[ReferenceImage, PropertyInfo(alias="referenceImage")]]
+ """Reference ad image to localize.
+
+ See [our docs](/assets/inputs#images) on image inputs.
+ """
+
+ target_language: Required[
+ Annotated[
+ Literal[
+ "ar",
+ "zh",
+ "zh-Hant",
+ "nl",
+ "en",
+ "fr",
+ "de",
+ "hi",
+ "id",
+ "it",
+ "ja",
+ "ko",
+ "pl",
+ "pt",
+ "ru",
+ "es",
+ "sv",
+ "th",
+ "tr",
+ "uk",
+ "vi",
+ "el",
+ ],
+ PropertyInfo(alias="targetLanguage"),
+ ]
+ ]
+ """Target language for the localized ad.
+
+ Use ISO-style codes (e.g. "ja" for Japanese, "es" for Spanish).
+ """
+
+ version: Required[Literal["2026-06", "unsafe-latest"]]
+ """Workflow version.
+
+ Use a dated version (e.g. "2026-06") to pin behavior, or "unsafe-latest" to
+ track the newest stable version (may break without notice).
+ """
+
+
+class ReferenceImage(TypedDict, total=False):
+ """Reference ad image to localize.
+
+ See [our docs](/assets/inputs#images) on image inputs.
+ """
+
+ uri: Required[str]
+ """A HTTPS URL."""
diff --git a/src/runwayml/types/recipe_ad_localization_response.py b/src/runwayml/types/recipe_ad_localization_response.py
new file mode 100644
index 0000000..5a97589
--- /dev/null
+++ b/src/runwayml/types/recipe_ad_localization_response.py
@@ -0,0 +1,10 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .._models import BaseModel
+
+__all__ = ["RecipeAdLocalizationResponse"]
+
+
+class RecipeAdLocalizationResponse(BaseModel):
+ id: str
+ """The ID of the task that was created. Use this to retrieve the task later."""
diff --git a/tests/api_resources/test_recipes.py b/tests/api_resources/test_recipes.py
index 4493307..07cbd7c 100644
--- a/tests/api_resources/test_recipes.py
+++ b/tests/api_resources/test_recipes.py
@@ -13,6 +13,7 @@
RecipeProductAdResponse,
RecipeProductUgcResponse,
RecipeProductSwapResponse,
+ RecipeAdLocalizationResponse,
RecipeMultiShotVideoResponse,
RecipeMarketingStockImageResponse,
RecipeProductCampaignImageResponse,
@@ -24,6 +25,43 @@
class TestRecipes:
parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+ @parametrize
+ def test_method_ad_localization(self, client: RunwayML) -> None:
+ recipe = client.recipes.ad_localization(
+ reference_image={"uri": "https://example.com/file"},
+ target_language="ar",
+ version="2026-06",
+ )
+ assert_matches_type(RecipeAdLocalizationResponse, recipe, path=["response"])
+
+ @parametrize
+ def test_raw_response_ad_localization(self, client: RunwayML) -> None:
+ response = client.recipes.with_raw_response.ad_localization(
+ reference_image={"uri": "https://example.com/file"},
+ target_language="ar",
+ version="2026-06",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ recipe = response.parse()
+ assert_matches_type(RecipeAdLocalizationResponse, recipe, path=["response"])
+
+ @parametrize
+ def test_streaming_response_ad_localization(self, client: RunwayML) -> None:
+ with client.recipes.with_streaming_response.ad_localization(
+ reference_image={"uri": "https://example.com/file"},
+ target_language="ar",
+ version="2026-06",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ recipe = response.parse()
+ assert_matches_type(RecipeAdLocalizationResponse, recipe, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
@parametrize
def test_method_marketing_stock_image(self, client: RunwayML) -> None:
recipe = client.recipes.marketing_stock_image(
@@ -421,6 +459,43 @@ class TestAsyncRecipes:
"async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
)
+ @parametrize
+ async def test_method_ad_localization(self, async_client: AsyncRunwayML) -> None:
+ recipe = await async_client.recipes.ad_localization(
+ reference_image={"uri": "https://example.com/file"},
+ target_language="ar",
+ version="2026-06",
+ )
+ assert_matches_type(RecipeAdLocalizationResponse, recipe, path=["response"])
+
+ @parametrize
+ async def test_raw_response_ad_localization(self, async_client: AsyncRunwayML) -> None:
+ response = await async_client.recipes.with_raw_response.ad_localization(
+ reference_image={"uri": "https://example.com/file"},
+ target_language="ar",
+ version="2026-06",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ recipe = await response.parse()
+ assert_matches_type(RecipeAdLocalizationResponse, recipe, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_ad_localization(self, async_client: AsyncRunwayML) -> None:
+ async with async_client.recipes.with_streaming_response.ad_localization(
+ reference_image={"uri": "https://example.com/file"},
+ target_language="ar",
+ version="2026-06",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ recipe = await response.parse()
+ assert_matches_type(RecipeAdLocalizationResponse, recipe, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
@parametrize
async def test_method_marketing_stock_image(self, async_client: AsyncRunwayML) -> None:
recipe = await async_client.recipes.marketing_stock_image(
From 51aec6ca6a4a02273e6296d78c24ac621a54d96e Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Mon, 6 Jul 2026 20:19:11 +0000
Subject: [PATCH 2/2] release: 5.9.0
---
.release-please-manifest.json | 2 +-
CHANGELOG.md | 8 ++++++++
pyproject.toml | 2 +-
src/runwayml/_version.py | 2 +-
4 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 8375aa0..8ed0bbc 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "5.8.0"
+ ".": "5.9.0"
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9416654..0c3264c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
# Changelog
+## 5.9.0 (2026-07-06)
+
+Full Changelog: [v5.8.0...v5.9.0](https://github.com/runwayml/sdk-python/compare/v5.8.0...v5.9.0)
+
+### Features
+
+* **api:** add ad_localization recipe ([0e13593](https://github.com/runwayml/sdk-python/commit/0e13593e38bbf7d0120182d390727593ecefb189))
+
## 5.8.0 (2026-07-06)
Full Changelog: [v5.7.0...v5.8.0](https://github.com/runwayml/sdk-python/compare/v5.7.0...v5.8.0)
diff --git a/pyproject.toml b/pyproject.toml
index 2d62054..05a4bc6 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "runwayml"
-version = "5.8.0"
+version = "5.9.0"
description = "The official Python library for the runwayml API"
dynamic = ["readme"]
license = "Apache-2.0"
diff --git a/src/runwayml/_version.py b/src/runwayml/_version.py
index 9b4ea71..0160beb 100644
--- a/src/runwayml/_version.py
+++ b/src/runwayml/_version.py
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
__title__ = "runwayml"
-__version__ = "5.8.0" # x-release-please-version
+__version__ = "5.9.0" # x-release-please-version