From 1d6c1180f8eaa71bfd45cae67360987b2bea3656 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 31 Jul 2026 14:57:24 +0000 Subject: [PATCH 1/2] feat(api): content provenance checks --- .stats.yml | 8 +- api.md | 12 + src/openai/__init__.py | 1 + src/openai/_client.py | 38 ++++ src/openai/_module_client.py | 8 + src/openai/resources/__init__.py | 14 ++ .../resources/beta/responses/responses.py | 36 ++- .../resources/content_provenance_checks.py | 206 ++++++++++++++++++ src/openai/resources/responses/responses.py | 36 ++- src/openai/types/__init__.py | 4 + .../types/beta/response_compact_params.py | 20 +- src/openai/types/content_provenance_check.py | 82 +++++++ .../content_provenance_check_create_params.py | 14 ++ .../responses/response_compact_params.py | 20 +- .../test_content_provenance_checks.py | 86 ++++++++ 15 files changed, 569 insertions(+), 16 deletions(-) create mode 100644 src/openai/resources/content_provenance_checks.py create mode 100644 src/openai/types/content_provenance_check.py create mode 100644 src/openai/types/content_provenance_check_create_params.py create mode 100644 tests/api_resources/test_content_provenance_checks.py diff --git a/.stats.yml b/.stats.yml index 5d31020c16..ec9ac4b5dd 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 278 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai/openai-44d4add500460ed21ac9ae1d6dd4047a32a79d3b4c3a9d9754f6ecf8cbdb9eec.yml -openapi_spec_hash: 8a34ba094583f56e975067493574fa69 -config_hash: ca12d10f1dbe101a81cd0376f868c674 +configured_endpoints: 279 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai/openai-31fcc3c97e5c432754bf0b72c5d5abbe1493573f0ca888af914baf81188b453e.yml +openapi_spec_hash: f867849a0c2a9c9b838d21f1c720a9e3 +config_hash: fce3820c4f95b555e486349bc7d297d8 diff --git a/api.md b/api.md index 7217cf566a..5a0325dc54 100644 --- a/api.md +++ b/api.md @@ -157,6 +157,18 @@ Methods: - client.images.edit(\*\*params) -> ImagesResponse - client.images.generate(\*\*params) -> ImagesResponse +# ContentProvenanceChecks + +Types: + +```python +from openai.types import ContentProvenanceCheck +``` + +Methods: + +- client.content_provenance_checks.create(\*\*params) -> ContentProvenanceCheck + # Audio Types: diff --git a/src/openai/__init__.py b/src/openai/__init__.py index 075a03a964..f59b47bb71 100644 --- a/src/openai/__init__.py +++ b/src/openai/__init__.py @@ -470,4 +470,5 @@ def _reset_client() -> None: # type: ignore[reportUnusedFunction] moderations as moderations, conversations as conversations, vector_stores as vector_stores, + content_provenance_checks as content_provenance_checks, ) diff --git a/src/openai/_client.py b/src/openai/_client.py index aeea9907a8..d7ca675b4d 100644 --- a/src/openai/_client.py +++ b/src/openai/_client.py @@ -64,6 +64,7 @@ moderations, conversations, vector_stores, + content_provenance_checks, ) from .resources.files import Files, AsyncFiles from .resources.images import Images, AsyncImages @@ -85,6 +86,7 @@ from .resources.responses.responses import Responses, AsyncResponses from .resources.containers.containers import Containers, AsyncContainers from .resources.fine_tuning.fine_tuning import FineTuning, AsyncFineTuning + from .resources.content_provenance_checks import ContentProvenanceChecks, AsyncContentProvenanceChecks from .resources.conversations.conversations import Conversations, AsyncConversations from .resources.vector_stores.vector_stores import VectorStores, AsyncVectorStores @@ -319,6 +321,12 @@ def images(self) -> Images: return Images(self) + @cached_property + def content_provenance_checks(self) -> ContentProvenanceChecks: + from .resources.content_provenance_checks import ContentProvenanceChecks + + return ContentProvenanceChecks(self) + @cached_property def audio(self) -> Audio: from .resources.audio import Audio @@ -919,6 +927,12 @@ def images(self) -> AsyncImages: return AsyncImages(self) + @cached_property + def content_provenance_checks(self) -> AsyncContentProvenanceChecks: + from .resources.content_provenance_checks import AsyncContentProvenanceChecks + + return AsyncContentProvenanceChecks(self) + @cached_property def audio(self) -> AsyncAudio: from .resources.audio import AsyncAudio @@ -1359,6 +1373,12 @@ def images(self) -> images.ImagesWithRawResponse: return ImagesWithRawResponse(self._client.images) + @cached_property + def content_provenance_checks(self) -> content_provenance_checks.ContentProvenanceChecksWithRawResponse: + from .resources.content_provenance_checks import ContentProvenanceChecksWithRawResponse + + return ContentProvenanceChecksWithRawResponse(self._client.content_provenance_checks) + @cached_property def audio(self) -> audio.AudioWithRawResponse: from .resources.audio import AudioWithRawResponse @@ -1510,6 +1530,12 @@ def images(self) -> images.AsyncImagesWithRawResponse: return AsyncImagesWithRawResponse(self._client.images) + @cached_property + def content_provenance_checks(self) -> content_provenance_checks.AsyncContentProvenanceChecksWithRawResponse: + from .resources.content_provenance_checks import AsyncContentProvenanceChecksWithRawResponse + + return AsyncContentProvenanceChecksWithRawResponse(self._client.content_provenance_checks) + @cached_property def audio(self) -> audio.AsyncAudioWithRawResponse: from .resources.audio import AsyncAudioWithRawResponse @@ -1661,6 +1687,12 @@ def images(self) -> images.ImagesWithStreamingResponse: return ImagesWithStreamingResponse(self._client.images) + @cached_property + def content_provenance_checks(self) -> content_provenance_checks.ContentProvenanceChecksWithStreamingResponse: + from .resources.content_provenance_checks import ContentProvenanceChecksWithStreamingResponse + + return ContentProvenanceChecksWithStreamingResponse(self._client.content_provenance_checks) + @cached_property def audio(self) -> audio.AudioWithStreamingResponse: from .resources.audio import AudioWithStreamingResponse @@ -1812,6 +1844,12 @@ def images(self) -> images.AsyncImagesWithStreamingResponse: return AsyncImagesWithStreamingResponse(self._client.images) + @cached_property + def content_provenance_checks(self) -> content_provenance_checks.AsyncContentProvenanceChecksWithStreamingResponse: + from .resources.content_provenance_checks import AsyncContentProvenanceChecksWithStreamingResponse + + return AsyncContentProvenanceChecksWithStreamingResponse(self._client.content_provenance_checks) + @cached_property def audio(self) -> audio.AsyncAudioWithStreamingResponse: from .resources.audio import AsyncAudioWithStreamingResponse diff --git a/src/openai/_module_client.py b/src/openai/_module_client.py index 3554e11e50..19c08c7589 100644 --- a/src/openai/_module_client.py +++ b/src/openai/_module_client.py @@ -26,6 +26,7 @@ from .resources.responses.responses import Responses from .resources.containers.containers import Containers from .resources.fine_tuning.fine_tuning import FineTuning + from .resources.content_provenance_checks import ContentProvenanceChecks from .resources.conversations.conversations import Conversations from .resources.vector_stores.vector_stores import VectorStores @@ -165,6 +166,12 @@ def __load__(self) -> Conversations: return _load_client().conversations +class ContentProvenanceChecksProxy(LazyProxy["ContentProvenanceChecks"]): + @override + def __load__(self) -> ContentProvenanceChecks: + return _load_client().content_provenance_checks + + chat: Chat = ChatProxy().__as_proxied__() beta: Beta = BetaProxy().__as_proxied__() files: Files = FilesProxy().__as_proxied__() @@ -187,3 +194,4 @@ def __load__(self) -> Conversations: fine_tuning: FineTuning = FineTuningProxy().__as_proxied__() vector_stores: VectorStores = VectorStoresProxy().__as_proxied__() conversations: Conversations = ConversationsProxy().__as_proxied__() +content_provenance_checks: ContentProvenanceChecks = ContentProvenanceChecksProxy().__as_proxied__() diff --git a/src/openai/resources/__init__.py b/src/openai/resources/__init__.py index e4905152c0..75bf79df0b 100644 --- a/src/openai/resources/__init__.py +++ b/src/openai/resources/__init__.py @@ -144,6 +144,14 @@ VectorStoresWithStreamingResponse, AsyncVectorStoresWithStreamingResponse, ) +from .content_provenance_checks import ( + ContentProvenanceChecks, + AsyncContentProvenanceChecks, + ContentProvenanceChecksWithRawResponse, + AsyncContentProvenanceChecksWithRawResponse, + ContentProvenanceChecksWithStreamingResponse, + AsyncContentProvenanceChecksWithStreamingResponse, +) __all__ = [ "Completions", @@ -176,6 +184,12 @@ "AsyncImagesWithRawResponse", "ImagesWithStreamingResponse", "AsyncImagesWithStreamingResponse", + "ContentProvenanceChecks", + "AsyncContentProvenanceChecks", + "ContentProvenanceChecksWithRawResponse", + "AsyncContentProvenanceChecksWithRawResponse", + "ContentProvenanceChecksWithStreamingResponse", + "AsyncContentProvenanceChecksWithStreamingResponse", "Audio", "AsyncAudio", "AudioWithRawResponse", diff --git a/src/openai/resources/beta/responses/responses.py b/src/openai/resources/beta/responses/responses.py index d926d4bd97..b10e169f89 100644 --- a/src/openai/resources/beta/responses/responses.py +++ b/src/openai/resources/beta/responses/responses.py @@ -1851,7 +1851,7 @@ def compact( prompt_cache_key: Optional[str] | Omit = omit, prompt_cache_options: Optional[response_compact_params.PromptCacheOptions] | Omit = omit, prompt_cache_retention: Optional[Literal["in_memory", "24h"]] | Omit = omit, - service_tier: Optional[Literal["auto", "default", "flex", "priority"]] | Omit = omit, + service_tier: Optional[Literal["auto", "default", "fast", "flex", "priority"]] | Omit = omit, betas: List[Literal["responses_multi_agent=v1"]] | Omit = omit, # 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. @@ -1902,7 +1902,21 @@ def compact( prompt_cache_retention: How long to retain a prompt cache entry created by this request. - service_tier: The service tier to use for this request. + service_tier: Specifies the processing type used for serving the request. - If set to 'auto', + then the request will be processed with the service tier configured in the + Project settings. Unless otherwise configured, the Project will use 'default'. - + If set to 'default', then the request will be processed with the standard + pricing and performance for the selected model. - If set to + '[flex](https://platform.openai.com/docs/guides/flex-processing)', then the + request will be processed with the Flex Processing service tier. - To opt-in to + [Fast mode](/api/docs/guides/fast-mode) at the request level, include the + `service_tier=fast` or `service_tier=priority` parameter for Responses or Chat + Completions. The response will show `service_tier=priority` regardless of if you + specify `service_tier=fast` or `priority` in your request. - When not set, the + default behavior is 'auto'. When the `service_tier` parameter is set, the + response body will include the `service_tier` value based on the processing mode + actually used to serve the request. This response value may be different from + the value set in the parameter. extra_headers: Send extra headers @@ -3745,7 +3759,7 @@ async def compact( prompt_cache_key: Optional[str] | Omit = omit, prompt_cache_options: Optional[response_compact_params.PromptCacheOptions] | Omit = omit, prompt_cache_retention: Optional[Literal["in_memory", "24h"]] | Omit = omit, - service_tier: Optional[Literal["auto", "default", "flex", "priority"]] | Omit = omit, + service_tier: Optional[Literal["auto", "default", "fast", "flex", "priority"]] | Omit = omit, betas: List[Literal["responses_multi_agent=v1"]] | Omit = omit, # 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. @@ -3796,7 +3810,21 @@ async def compact( prompt_cache_retention: How long to retain a prompt cache entry created by this request. - service_tier: The service tier to use for this request. + service_tier: Specifies the processing type used for serving the request. - If set to 'auto', + then the request will be processed with the service tier configured in the + Project settings. Unless otherwise configured, the Project will use 'default'. - + If set to 'default', then the request will be processed with the standard + pricing and performance for the selected model. - If set to + '[flex](https://platform.openai.com/docs/guides/flex-processing)', then the + request will be processed with the Flex Processing service tier. - To opt-in to + [Fast mode](/api/docs/guides/fast-mode) at the request level, include the + `service_tier=fast` or `service_tier=priority` parameter for Responses or Chat + Completions. The response will show `service_tier=priority` regardless of if you + specify `service_tier=fast` or `priority` in your request. - When not set, the + default behavior is 'auto'. When the `service_tier` parameter is set, the + response body will include the `service_tier` value based on the processing mode + actually used to serve the request. This response value may be different from + the value set in the parameter. extra_headers: Send extra headers diff --git a/src/openai/resources/content_provenance_checks.py b/src/openai/resources/content_provenance_checks.py new file mode 100644 index 0000000000..9e01179e31 --- /dev/null +++ b/src/openai/resources/content_provenance_checks.py @@ -0,0 +1,206 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Mapping, cast + +import httpx + +from .. import _legacy_response +from ..types import content_provenance_check_create_params +from .._files import deepcopy_with_paths +from .._types import Body, Query, Headers, NotGiven, FileTypes, not_given +from .._utils import extract_files, maybe_transform, async_maybe_transform +from .._compat import cached_property +from .._resource import SyncAPIResource, AsyncAPIResource +from .._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper +from .._base_client import make_request_options +from ..types.content_provenance_check import ContentProvenanceCheck + +__all__ = ["ContentProvenanceChecks", "AsyncContentProvenanceChecks"] + + +class ContentProvenanceChecks(SyncAPIResource): + @cached_property + def with_raw_response(self) -> ContentProvenanceChecksWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers + """ + return ContentProvenanceChecksWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> ContentProvenanceChecksWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/openai/openai-python#with_streaming_response + """ + return ContentProvenanceChecksWithStreamingResponse(self) + + def create( + self, + *, + file: FileTypes, + # 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, + ) -> ContentProvenanceCheck: + """ + Check whether an image or audio file contains known OpenAI provenance signals. + [Learn more about content provenance](/api/docs/guides/content-provenance). + + If `not_detected`, it means the tool did not find supported signals in the + uploaded file. The content could still have been generated by OpenAI if the + metadata was stripped or has evidence of tampering, the watermark was degraded, + it comes from a legacy generation model, or it was created before provenance + signals were available. Content could also still be AI-generated by another + company's model, which the tool currently does not detect. + + Args: + file: The image or audio file to check for supported OpenAI provenance signals. + + 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 + """ + body = deepcopy_with_paths({"file": file}, [["file"]]) + files = extract_files(cast(Mapping[str, object], body), paths=[["file"]]) + # It should be noted that the actual Content-Type header that will be + # sent to the server will contain a `boundary` parameter, e.g. + # multipart/form-data; boundary=---abc-- + extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} + return self._post( + "/content_provenance_checks", + body=maybe_transform(body, content_provenance_check_create_params.ContentProvenanceCheckCreateParams), + files=files, + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + security={"bearer_auth": True}, + ), + cast_to=ContentProvenanceCheck, + ) + + +class AsyncContentProvenanceChecks(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncContentProvenanceChecksWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers + """ + return AsyncContentProvenanceChecksWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncContentProvenanceChecksWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/openai/openai-python#with_streaming_response + """ + return AsyncContentProvenanceChecksWithStreamingResponse(self) + + async def create( + self, + *, + file: FileTypes, + # 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, + ) -> ContentProvenanceCheck: + """ + Check whether an image or audio file contains known OpenAI provenance signals. + [Learn more about content provenance](/api/docs/guides/content-provenance). + + If `not_detected`, it means the tool did not find supported signals in the + uploaded file. The content could still have been generated by OpenAI if the + metadata was stripped or has evidence of tampering, the watermark was degraded, + it comes from a legacy generation model, or it was created before provenance + signals were available. Content could also still be AI-generated by another + company's model, which the tool currently does not detect. + + Args: + file: The image or audio file to check for supported OpenAI provenance signals. + + 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 + """ + body = deepcopy_with_paths({"file": file}, [["file"]]) + files = extract_files(cast(Mapping[str, object], body), paths=[["file"]]) + # It should be noted that the actual Content-Type header that will be + # sent to the server will contain a `boundary` parameter, e.g. + # multipart/form-data; boundary=---abc-- + extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} + return await self._post( + "/content_provenance_checks", + body=await async_maybe_transform( + body, content_provenance_check_create_params.ContentProvenanceCheckCreateParams + ), + files=files, + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + security={"bearer_auth": True}, + ), + cast_to=ContentProvenanceCheck, + ) + + +class ContentProvenanceChecksWithRawResponse: + def __init__(self, content_provenance_checks: ContentProvenanceChecks) -> None: + self._content_provenance_checks = content_provenance_checks + + self.create = _legacy_response.to_raw_response_wrapper( + content_provenance_checks.create, + ) + + +class AsyncContentProvenanceChecksWithRawResponse: + def __init__(self, content_provenance_checks: AsyncContentProvenanceChecks) -> None: + self._content_provenance_checks = content_provenance_checks + + self.create = _legacy_response.async_to_raw_response_wrapper( + content_provenance_checks.create, + ) + + +class ContentProvenanceChecksWithStreamingResponse: + def __init__(self, content_provenance_checks: ContentProvenanceChecks) -> None: + self._content_provenance_checks = content_provenance_checks + + self.create = to_streamed_response_wrapper( + content_provenance_checks.create, + ) + + +class AsyncContentProvenanceChecksWithStreamingResponse: + def __init__(self, content_provenance_checks: AsyncContentProvenanceChecks) -> None: + self._content_provenance_checks = content_provenance_checks + + self.create = async_to_streamed_response_wrapper( + content_provenance_checks.create, + ) diff --git a/src/openai/resources/responses/responses.py b/src/openai/resources/responses/responses.py index d0e0bed257..344f7cbb54 100644 --- a/src/openai/resources/responses/responses.py +++ b/src/openai/resources/responses/responses.py @@ -1823,7 +1823,7 @@ def compact( prompt_cache_key: Optional[str] | Omit = omit, prompt_cache_options: Optional[response_compact_params.PromptCacheOptions] | Omit = omit, prompt_cache_retention: Optional[Literal["in_memory", "24h"]] | Omit = omit, - service_tier: Optional[Literal["auto", "default", "flex", "priority"]] | Omit = omit, + service_tier: Optional[Literal["auto", "default", "fast", "flex", "priority"]] | Omit = omit, # 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, @@ -1873,7 +1873,21 @@ def compact( prompt_cache_retention: How long to retain a prompt cache entry created by this request. - service_tier: The service tier to use for this request. + service_tier: Specifies the processing type used for serving the request. - If set to 'auto', + then the request will be processed with the service tier configured in the + Project settings. Unless otherwise configured, the Project will use 'default'. - + If set to 'default', then the request will be processed with the standard + pricing and performance for the selected model. - If set to + '[flex](https://platform.openai.com/docs/guides/flex-processing)', then the + request will be processed with the Flex Processing service tier. - To opt-in to + [Fast mode](/api/docs/guides/fast-mode) at the request level, include the + `service_tier=fast` or `service_tier=priority` parameter for Responses or Chat + Completions. The response will show `service_tier=priority` regardless of if you + specify `service_tier=fast` or `priority` in your request. - When not set, the + default behavior is 'auto'. When the `service_tier` parameter is set, the + response body will include the `service_tier` value based on the processing mode + actually used to serve the request. This response value may be different from + the value set in the parameter. extra_headers: Send extra headers @@ -3657,7 +3671,7 @@ async def compact( prompt_cache_key: Optional[str] | Omit = omit, prompt_cache_options: Optional[response_compact_params.PromptCacheOptions] | Omit = omit, prompt_cache_retention: Optional[Literal["in_memory", "24h"]] | Omit = omit, - service_tier: Optional[Literal["auto", "default", "flex", "priority"]] | Omit = omit, + service_tier: Optional[Literal["auto", "default", "fast", "flex", "priority"]] | Omit = omit, # 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, @@ -3707,7 +3721,21 @@ async def compact( prompt_cache_retention: How long to retain a prompt cache entry created by this request. - service_tier: The service tier to use for this request. + service_tier: Specifies the processing type used for serving the request. - If set to 'auto', + then the request will be processed with the service tier configured in the + Project settings. Unless otherwise configured, the Project will use 'default'. - + If set to 'default', then the request will be processed with the standard + pricing and performance for the selected model. - If set to + '[flex](https://platform.openai.com/docs/guides/flex-processing)', then the + request will be processed with the Flex Processing service tier. - To opt-in to + [Fast mode](/api/docs/guides/fast-mode) at the request level, include the + `service_tier=fast` or `service_tier=priority` parameter for Responses or Chat + Completions. The response will show `service_tier=priority` regardless of if you + specify `service_tier=fast` or `priority` in your request. - When not set, the + default behavior is 'auto'. When the `service_tier` parameter is set, the + response body will include the `service_tier` value based on the processing mode + actually used to serve the request. This response value may be different from + the value set in the parameter. extra_headers: Send extra headers diff --git a/src/openai/types/__init__.py b/src/openai/types/__init__.py index dc2c8a348c..e855bc06f7 100644 --- a/src/openai/types/__init__.py +++ b/src/openai/types/__init__.py @@ -94,6 +94,7 @@ from .embedding_create_params import EmbeddingCreateParams as EmbeddingCreateParams from .image_edit_stream_event import ImageEditStreamEvent as ImageEditStreamEvent from .completion_create_params import CompletionCreateParams as CompletionCreateParams +from .content_provenance_check import ContentProvenanceCheck as ContentProvenanceCheck from .moderation_create_params import ModerationCreateParams as ModerationCreateParams from .vector_store_list_params import VectorStoreListParams as VectorStoreListParams from .container_create_response import ContainerCreateResponse as ContainerCreateResponse @@ -128,6 +129,9 @@ from .other_file_chunking_strategy_object import OtherFileChunkingStrategyObject as OtherFileChunkingStrategyObject from .static_file_chunking_strategy_param import StaticFileChunkingStrategyParam as StaticFileChunkingStrategyParam from .static_file_chunking_strategy_object import StaticFileChunkingStrategyObject as StaticFileChunkingStrategyObject +from .content_provenance_check_create_params import ( + ContentProvenanceCheckCreateParams as ContentProvenanceCheckCreateParams, +) from .eval_stored_completions_data_source_config import ( EvalStoredCompletionsDataSourceConfig as EvalStoredCompletionsDataSourceConfig, ) diff --git a/src/openai/types/beta/response_compact_params.py b/src/openai/types/beta/response_compact_params.py index 8e8a821521..219fc0f8c3 100644 --- a/src/openai/types/beta/response_compact_params.py +++ b/src/openai/types/beta/response_compact_params.py @@ -162,8 +162,24 @@ class ResponseCompactParams(TypedDict, total=False): prompt_cache_retention: Optional[Literal["in_memory", "24h"]] """How long to retain a prompt cache entry created by this request.""" - service_tier: Optional[Literal["auto", "default", "flex", "priority"]] - """The service tier to use for this request.""" + service_tier: Optional[Literal["auto", "default", "fast", "flex", "priority"]] + """Specifies the processing type used for serving the request. + + - If set to 'auto', then the request will be processed with the service tier + configured in the Project settings. Unless otherwise configured, the Project + will use 'default'. - If set to 'default', then the request will be processed + with the standard pricing and performance for the selected model. - If set to + '[flex](https://platform.openai.com/docs/guides/flex-processing)', then the + request will be processed with the Flex Processing service tier. - To opt-in + to [Fast mode](/api/docs/guides/fast-mode) at the request level, include the + `service_tier=fast` or `service_tier=priority` parameter for Responses or Chat + Completions. The response will show `service_tier=priority` regardless of if + you specify `service_tier=fast` or `priority` in your request. - When not set, + the default behavior is 'auto'. When the `service_tier` parameter is set, the + response body will include the `service_tier` value based on the processing + mode actually used to serve the request. This response value may be different + from the value set in the parameter. + """ betas: Annotated[List[Literal["responses_multi_agent=v1"]], PropertyInfo(alias="openai-beta")] diff --git a/src/openai/types/content_provenance_check.py b/src/openai/types/content_provenance_check.py new file mode 100644 index 0000000000..01de63a66e --- /dev/null +++ b/src/openai/types/content_provenance_check.py @@ -0,0 +1,82 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Union, Optional +from typing_extensions import Literal, Annotated, TypeAlias + +from .._utils import PropertyInfo +from .._models import BaseModel + +__all__ = ["ContentProvenanceCheck", "Result", "ResultC2PA", "ResultSynthID"] + + +class ResultC2PA(BaseModel): + generated_at: Optional[str] = None + """ + The UTC RFC 3339 timestamp recorded by the provenance signal for when the asset + was generated, when available. + """ + + issuer: Optional[str] = None + """The C2PA manifest issuer, when available.""" + + model: Optional[str] = None + """The OpenAI model recorded by the provenance signal, when available.""" + + outcome: Literal["detected", "not_detected"] + """ + Whether a supported OpenAI C2PA provenance signal was detected. If + `not_detected`, it means the tool did not find supported signals in the uploaded + file. The content could still have been generated by OpenAI if the metadata was + stripped or has evidence of tampering, the watermark was degraded, it comes from + a legacy generation model, or it was created before provenance signals were + available. Content could also still be AI-generated by another company's model, + which the tool currently does not detect. + """ + + type: Literal["c2pa"] + """The provenance signal type. Always `c2pa`.""" + + validation_state: Literal["trusted", "valid", "invalid", "not_present"] + """The validation status of the C2PA manifest in the uploaded image.""" + + +class ResultSynthID(BaseModel): + generated_at: Optional[str] = None + """ + The UTC RFC 3339 timestamp recorded by the provenance signal for when the asset + was generated, when available. + """ + + model: Optional[str] = None + """The OpenAI model recorded by the provenance signal, when available.""" + + outcome: Literal["detected", "not_detected"] + """ + Whether a supported OpenAI SynthID watermark was detected. If `not_detected`, it + means the tool did not find supported signals in the uploaded file. The content + could still have been generated by OpenAI if the metadata was stripped or has + evidence of tampering, the watermark was degraded, it comes from a legacy + generation model, or it was created before provenance signals were available. + Content could also still be AI-generated by another company's model, which the + tool currently does not detect. + """ + + type: Literal["synthid"] + """The provenance signal type. Always `synthid`.""" + + +Result: TypeAlias = Annotated[Union[ResultC2PA, ResultSynthID], PropertyInfo(discriminator="type")] + + +class ContentProvenanceCheck(BaseModel): + created_at: int + """The Unix timestamp, in seconds, when the provenance check was created.""" + + object: Literal["content_provenance_check"] + """The object type. Always `content_provenance_check` for this endpoint.""" + + results: List[Result] + """The provenance results that apply to the uploaded file. + + Image results include C2PA and SynthID; audio results include SynthID. + """ diff --git a/src/openai/types/content_provenance_check_create_params.py b/src/openai/types/content_provenance_check_create_params.py new file mode 100644 index 0000000000..6afc724721 --- /dev/null +++ b/src/openai/types/content_provenance_check_create_params.py @@ -0,0 +1,14 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +from .._types import FileTypes + +__all__ = ["ContentProvenanceCheckCreateParams"] + + +class ContentProvenanceCheckCreateParams(TypedDict, total=False): + file: Required[FileTypes] + """The image or audio file to check for supported OpenAI provenance signals.""" diff --git a/src/openai/types/responses/response_compact_params.py b/src/openai/types/responses/response_compact_params.py index 3f3bc73465..0c291acaaf 100644 --- a/src/openai/types/responses/response_compact_params.py +++ b/src/openai/types/responses/response_compact_params.py @@ -161,8 +161,24 @@ class ResponseCompactParams(TypedDict, total=False): prompt_cache_retention: Optional[Literal["in_memory", "24h"]] """How long to retain a prompt cache entry created by this request.""" - service_tier: Optional[Literal["auto", "default", "flex", "priority"]] - """The service tier to use for this request.""" + service_tier: Optional[Literal["auto", "default", "fast", "flex", "priority"]] + """Specifies the processing type used for serving the request. + + - If set to 'auto', then the request will be processed with the service tier + configured in the Project settings. Unless otherwise configured, the Project + will use 'default'. - If set to 'default', then the request will be processed + with the standard pricing and performance for the selected model. - If set to + '[flex](https://platform.openai.com/docs/guides/flex-processing)', then the + request will be processed with the Flex Processing service tier. - To opt-in + to [Fast mode](/api/docs/guides/fast-mode) at the request level, include the + `service_tier=fast` or `service_tier=priority` parameter for Responses or Chat + Completions. The response will show `service_tier=priority` regardless of if + you specify `service_tier=fast` or `priority` in your request. - When not set, + the default behavior is 'auto'. When the `service_tier` parameter is set, the + response body will include the `service_tier` value based on the processing + mode actually used to serve the request. This response value may be different + from the value set in the parameter. + """ class PromptCacheOptions(TypedDict, total=False): diff --git a/tests/api_resources/test_content_provenance_checks.py b/tests/api_resources/test_content_provenance_checks.py new file mode 100644 index 0000000000..f24995b051 --- /dev/null +++ b/tests/api_resources/test_content_provenance_checks.py @@ -0,0 +1,86 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from openai import OpenAI, AsyncOpenAI +from tests.utils import assert_matches_type +from openai.types import ContentProvenanceCheck + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestContentProvenanceChecks: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_create(self, client: OpenAI) -> None: + content_provenance_check = client.content_provenance_checks.create( + file=b"Example data", + ) + assert_matches_type(ContentProvenanceCheck, content_provenance_check, path=["response"]) + + @parametrize + def test_raw_response_create(self, client: OpenAI) -> None: + response = client.content_provenance_checks.with_raw_response.create( + file=b"Example data", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + content_provenance_check = response.parse() + assert_matches_type(ContentProvenanceCheck, content_provenance_check, path=["response"]) + + @parametrize + def test_streaming_response_create(self, client: OpenAI) -> None: + with client.content_provenance_checks.with_streaming_response.create( + file=b"Example data", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + content_provenance_check = response.parse() + assert_matches_type(ContentProvenanceCheck, content_provenance_check, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncContentProvenanceChecks: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @parametrize + async def test_method_create(self, async_client: AsyncOpenAI) -> None: + content_provenance_check = await async_client.content_provenance_checks.create( + file=b"Example data", + ) + assert_matches_type(ContentProvenanceCheck, content_provenance_check, path=["response"]) + + @parametrize + async def test_raw_response_create(self, async_client: AsyncOpenAI) -> None: + response = await async_client.content_provenance_checks.with_raw_response.create( + file=b"Example data", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + content_provenance_check = response.parse() + assert_matches_type(ContentProvenanceCheck, content_provenance_check, path=["response"]) + + @parametrize + async def test_streaming_response_create(self, async_client: AsyncOpenAI) -> None: + async with async_client.content_provenance_checks.with_streaming_response.create( + file=b"Example data", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + content_provenance_check = await response.parse() + assert_matches_type(ContentProvenanceCheck, content_provenance_check, path=["response"]) + + assert cast(Any, response.is_closed) is True From e0657723003a34ff62e235306c99627ed3b68d33 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 31 Jul 2026 14:58:57 +0000 Subject: [PATCH 2/2] release: 2.52.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 18 ++++++++++++++++++ pyproject.toml | 2 +- src/openai/_version.py | 2 +- 4 files changed, 21 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 318899b64d..436fe1fcdc 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "2.51.0" + ".": "2.52.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 48e1f8cc72..73dd3511d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,23 @@ # Changelog +## 2.52.0 (2026-07-31) + +Full Changelog: [v2.51.0...v2.52.0](https://github.com/openai/openai-python/compare/v2.51.0...v2.52.0) + +### Features + +* **api:** content provenance checks ([1d6c118](https://github.com/openai/openai-python/commit/1d6c1180f8eaa71bfd45cae67360987b2bea3656)) + + +### Bug Fixes + +* **client:** honor Retry-After delays up to two minutes ([#3555](https://github.com/openai/openai-python/issues/3555)) ([7fa7946](https://github.com/openai/openai-python/commit/7fa7946485b5ecbadd0ebf8624c574e2c9e3370c)) + + +### Documentation + +* add API-key mTLS HTTP client recipes ([#3552](https://github.com/openai/openai-python/issues/3552)) ([7a3d5e4](https://github.com/openai/openai-python/commit/7a3d5e46b61cb36109dc4e7fd6d4ab70cc6d6c0f)) + ## 2.51.0 (2026-07-30) Full Changelog: [v2.50.0...v2.51.0](https://github.com/openai/openai-python/compare/v2.50.0...v2.51.0) diff --git a/pyproject.toml b/pyproject.toml index b5afe38113..f32ea2f5ae 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "openai" -version = "2.51.0" +version = "2.52.0" description = "The official Python library for the openai API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/openai/_version.py b/src/openai/_version.py index 8438cbcc19..c571d18405 100644 --- a/src/openai/_version.py +++ b/src/openai/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "openai" -__version__ = "2.51.0" # x-release-please-version +__version__ = "2.52.0" # x-release-please-version