Commit 0673da62

stainless-app[bot] <142633134+stainless-app[bot]@users.noreply.github.com>
2025-06-24 02:26:16
release: 1.91.0 (#2423) tag: v1.91.0
* feat(api): update api shapes for usage and code interpreter * release: 1.91.0 --------- Co-authored-by: stainless-app[bot] <142633134+stainless-app[bot]@users.noreply.github.com>
1 parent e689216
src/openai/resources/audio/speech.py
@@ -56,6 +56,7 @@ class Speech(SyncAPIResource):
         instructions: str | NotGiven = NOT_GIVEN,
         response_format: Literal["mp3", "opus", "aac", "flac", "wav", "pcm"] | NotGiven = NOT_GIVEN,
         speed: float | NotGiven = NOT_GIVEN,
+        stream_format: Literal["sse", "audio"] | NotGiven = NOT_GIVEN,
         # 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,
@@ -85,7 +86,10 @@ class Speech(SyncAPIResource):
               `wav`, and `pcm`.
 
           speed: The speed of the generated audio. Select a value from `0.25` to `4.0`. `1.0` is
-              the default. Does not work with `gpt-4o-mini-tts`.
+              the default.
+
+          stream_format: The format to stream the audio in. Supported formats are `sse` and `audio`.
+              `sse` is not supported for `tts-1` or `tts-1-hd`.
 
           extra_headers: Send extra headers
 
@@ -106,6 +110,7 @@ class Speech(SyncAPIResource):
                     "instructions": instructions,
                     "response_format": response_format,
                     "speed": speed,
+                    "stream_format": stream_format,
                 },
                 speech_create_params.SpeechCreateParams,
             ),
@@ -147,6 +152,7 @@ class AsyncSpeech(AsyncAPIResource):
         instructions: str | NotGiven = NOT_GIVEN,
         response_format: Literal["mp3", "opus", "aac", "flac", "wav", "pcm"] | NotGiven = NOT_GIVEN,
         speed: float | NotGiven = NOT_GIVEN,
+        stream_format: Literal["sse", "audio"] | NotGiven = NOT_GIVEN,
         # 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,
@@ -176,7 +182,10 @@ class AsyncSpeech(AsyncAPIResource):
               `wav`, and `pcm`.
 
           speed: The speed of the generated audio. Select a value from `0.25` to `4.0`. `1.0` is
-              the default. Does not work with `gpt-4o-mini-tts`.
+              the default.
+
+          stream_format: The format to stream the audio in. Supported formats are `sse` and `audio`.
+              `sse` is not supported for `tts-1` or `tts-1-hd`.
 
           extra_headers: Send extra headers
 
@@ -197,6 +206,7 @@ class AsyncSpeech(AsyncAPIResource):
                     "instructions": instructions,
                     "response_format": response_format,
                     "speed": speed,
+                    "stream_format": stream_format,
                 },
                 speech_create_params.SpeechCreateParams,
             ),
src/openai/resources/fine_tuning/checkpoints/permissions.py
@@ -9,11 +9,11 @@ import httpx
 
 from .... import _legacy_response
 from ...._types import NOT_GIVEN, Body, Query, Headers, NotGiven
-from ...._utils import maybe_transform
+from ...._utils import 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 ....pagination import SyncPage, AsyncPage, SyncCursorPage, AsyncCursorPage
+from ....pagination import SyncPage, AsyncPage
 from ...._base_client import AsyncPaginator, make_request_options
 from ....types.fine_tuning.checkpoints import permission_create_params, permission_retrieve_params
 from ....types.fine_tuning.checkpoints.permission_create_response import PermissionCreateResponse
@@ -101,7 +101,7 @@ class Permissions(SyncAPIResource):
         extra_query: Query | None = None,
         extra_body: Body | None = None,
         timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
-    ) -> SyncCursorPage[PermissionRetrieveResponse]:
+    ) -> PermissionRetrieveResponse:
         """
         **NOTE:** This endpoint requires an [admin API key](../admin-api-keys).
 
@@ -129,9 +129,8 @@ class Permissions(SyncAPIResource):
             raise ValueError(
                 f"Expected a non-empty value for `fine_tuned_model_checkpoint` but received {fine_tuned_model_checkpoint!r}"
             )
-        return self._get_api_list(
+        return self._get(
             f"/fine_tuning/checkpoints/{fine_tuned_model_checkpoint}/permissions",
-            page=SyncCursorPage[PermissionRetrieveResponse],
             options=make_request_options(
                 extra_headers=extra_headers,
                 extra_query=extra_query,
@@ -147,7 +146,7 @@ class Permissions(SyncAPIResource):
                     permission_retrieve_params.PermissionRetrieveParams,
                 ),
             ),
-            model=PermissionRetrieveResponse,
+            cast_to=PermissionRetrieveResponse,
         )
 
     def delete(
@@ -256,7 +255,7 @@ class AsyncPermissions(AsyncAPIResource):
             method="post",
         )
 
-    def retrieve(
+    async def retrieve(
         self,
         fine_tuned_model_checkpoint: str,
         *,
@@ -270,7 +269,7 @@ class AsyncPermissions(AsyncAPIResource):
         extra_query: Query | None = None,
         extra_body: Body | None = None,
         timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
-    ) -> AsyncPaginator[PermissionRetrieveResponse, AsyncCursorPage[PermissionRetrieveResponse]]:
+    ) -> PermissionRetrieveResponse:
         """
         **NOTE:** This endpoint requires an [admin API key](../admin-api-keys).
 
@@ -298,15 +297,14 @@ class AsyncPermissions(AsyncAPIResource):
             raise ValueError(
                 f"Expected a non-empty value for `fine_tuned_model_checkpoint` but received {fine_tuned_model_checkpoint!r}"
             )
-        return self._get_api_list(
+        return await self._get(
             f"/fine_tuning/checkpoints/{fine_tuned_model_checkpoint}/permissions",
-            page=AsyncCursorPage[PermissionRetrieveResponse],
             options=make_request_options(
                 extra_headers=extra_headers,
                 extra_query=extra_query,
                 extra_body=extra_body,
                 timeout=timeout,
-                query=maybe_transform(
+                query=await async_maybe_transform(
                     {
                         "after": after,
                         "limit": limit,
@@ -316,7 +314,7 @@ class AsyncPermissions(AsyncAPIResource):
                     permission_retrieve_params.PermissionRetrieveParams,
                 ),
             ),
-            model=PermissionRetrieveResponse,
+            cast_to=PermissionRetrieveResponse,
         )
 
     async def delete(
src/openai/types/audio/speech_create_params.py
@@ -48,6 +48,12 @@ class SpeechCreateParams(TypedDict, total=False):
     speed: float
     """The speed of the generated audio.
 
-    Select a value from `0.25` to `4.0`. `1.0` is the default. Does not work with
-    `gpt-4o-mini-tts`.
+    Select a value from `0.25` to `4.0`. `1.0` is the default.
+    """
+
+    stream_format: Literal["sse", "audio"]
+    """The format to stream the audio in.
+
+    Supported formats are `sse` and `audio`. `sse` is not supported for `tts-1` or
+    `tts-1-hd`.
     """
src/openai/types/audio/transcription.py
@@ -1,10 +1,12 @@
 # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
 
-from typing import List, Optional
+from typing import List, Union, Optional
+from typing_extensions import Literal, Annotated, TypeAlias
 
+from ..._utils import PropertyInfo
 from ..._models import BaseModel
 
-__all__ = ["Transcription", "Logprob"]
+__all__ = ["Transcription", "Logprob", "Usage", "UsageTokens", "UsageTokensInputTokenDetails", "UsageDuration"]
 
 
 class Logprob(BaseModel):
@@ -18,6 +20,42 @@ class Logprob(BaseModel):
     """The log probability of the token."""
 
 
+class UsageTokensInputTokenDetails(BaseModel):
+    audio_tokens: Optional[int] = None
+    """Number of audio tokens billed for this request."""
+
+    text_tokens: Optional[int] = None
+    """Number of text tokens billed for this request."""
+
+
+class UsageTokens(BaseModel):
+    input_tokens: int
+    """Number of input tokens billed for this request."""
+
+    output_tokens: int
+    """Number of output tokens generated."""
+
+    total_tokens: int
+    """Total number of tokens used (input + output)."""
+
+    type: Literal["tokens"]
+    """The type of the usage object. Always `tokens` for this variant."""
+
+    input_token_details: Optional[UsageTokensInputTokenDetails] = None
+    """Details about the input tokens billed for this request."""
+
+
+class UsageDuration(BaseModel):
+    duration: float
+    """Duration of the input audio in seconds."""
+
+    type: Literal["duration"]
+    """The type of the usage object. Always `duration` for this variant."""
+
+
+Usage: TypeAlias = Annotated[Union[UsageTokens, UsageDuration], PropertyInfo(discriminator="type")]
+
+
 class Transcription(BaseModel):
     text: str
     """The transcribed text."""
@@ -28,3 +66,6 @@ class Transcription(BaseModel):
     Only returned with the models `gpt-4o-transcribe` and `gpt-4o-mini-transcribe`
     if `logprobs` is added to the `include` array.
     """
+
+    usage: Optional[Usage] = None
+    """Token usage statistics for the request."""
src/openai/types/audio/transcription_text_done_event.py
@@ -5,7 +5,7 @@ from typing_extensions import Literal
 
 from ..._models import BaseModel
 
-__all__ = ["TranscriptionTextDoneEvent", "Logprob"]
+__all__ = ["TranscriptionTextDoneEvent", "Logprob", "Usage", "UsageInputTokenDetails"]
 
 
 class Logprob(BaseModel):
@@ -19,6 +19,31 @@ class Logprob(BaseModel):
     """The log probability of the token."""
 
 
+class UsageInputTokenDetails(BaseModel):
+    audio_tokens: Optional[int] = None
+    """Number of audio tokens billed for this request."""
+
+    text_tokens: Optional[int] = None
+    """Number of text tokens billed for this request."""
+
+
+class Usage(BaseModel):
+    input_tokens: int
+    """Number of input tokens billed for this request."""
+
+    output_tokens: int
+    """Number of output tokens generated."""
+
+    total_tokens: int
+    """Total number of tokens used (input + output)."""
+
+    type: Literal["tokens"]
+    """The type of the usage object. Always `tokens` for this variant."""
+
+    input_token_details: Optional[UsageInputTokenDetails] = None
+    """Details about the input tokens billed for this request."""
+
+
 class TranscriptionTextDoneEvent(BaseModel):
     text: str
     """The text that was transcribed."""
@@ -33,3 +58,6 @@ class TranscriptionTextDoneEvent(BaseModel):
     [create a transcription](https://platform.openai.com/docs/api-reference/audio/create-transcription)
     with the `include[]` parameter set to `logprobs`.
     """
+
+    usage: Optional[Usage] = None
+    """Usage statistics for models billed by token usage."""
src/openai/types/audio/transcription_verbose.py
@@ -1,12 +1,21 @@
 # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
 
 from typing import List, Optional
+from typing_extensions import Literal
 
 from ..._models import BaseModel
 from .transcription_word import TranscriptionWord
 from .transcription_segment import TranscriptionSegment
 
-__all__ = ["TranscriptionVerbose"]
+__all__ = ["TranscriptionVerbose", "Usage"]
+
+
+class Usage(BaseModel):
+    duration: float
+    """Duration of the input audio in seconds."""
+
+    type: Literal["duration"]
+    """The type of the usage object. Always `duration` for this variant."""
 
 
 class TranscriptionVerbose(BaseModel):
@@ -22,5 +31,8 @@ class TranscriptionVerbose(BaseModel):
     segments: Optional[List[TranscriptionSegment]] = None
     """Segments of the transcribed text and their corresponding details."""
 
+    usage: Optional[Usage] = None
+    """Usage statistics for models billed by audio input duration."""
+
     words: Optional[List[TranscriptionWord]] = None
     """Extracted words and their corresponding timestamps."""
src/openai/types/beta/realtime/session_create_params.py
@@ -3,12 +3,12 @@
 from __future__ import annotations
 
 from typing import List, Union, Iterable
-from typing_extensions import Literal, TypeAlias, TypedDict
+from typing_extensions import Literal, Required, TypeAlias, TypedDict
 
 __all__ = [
     "SessionCreateParams",
     "ClientSecret",
-    "ClientSecretExpiresAt",
+    "ClientSecretExpiresAfter",
     "InputAudioNoiseReduction",
     "InputAudioTranscription",
     "Tool",
@@ -156,8 +156,8 @@ class SessionCreateParams(TypedDict, total=False):
     """
 
 
-class ClientSecretExpiresAt(TypedDict, total=False):
-    anchor: Literal["created_at"]
+class ClientSecretExpiresAfter(TypedDict, total=False):
+    anchor: Required[Literal["created_at"]]
     """The anchor point for the ephemeral token expiration.
 
     Only `created_at` is currently supported.
@@ -171,7 +171,7 @@ class ClientSecretExpiresAt(TypedDict, total=False):
 
 
 class ClientSecret(TypedDict, total=False):
-    expires_at: ClientSecretExpiresAt
+    expires_after: ClientSecretExpiresAfter
     """Configuration for the ephemeral token expiration."""
 
 
src/openai/types/beta/realtime/session_create_response.py
@@ -33,10 +33,7 @@ class ClientSecret(BaseModel):
 
 class InputAudioTranscription(BaseModel):
     model: Optional[str] = None
-    """
-    The model to use for transcription, `whisper-1` is the only currently supported
-    model.
-    """
+    """The model to use for transcription."""
 
 
 class Tool(BaseModel):
@@ -116,8 +113,8 @@ class SessionCreateResponse(BaseModel):
     Configuration for input audio transcription, defaults to off and can be set to
     `null` to turn off once on. Input audio transcription is not native to the
     model, since the model consumes audio directly. Transcription runs
-    asynchronously through Whisper and should be treated as rough guidance rather
-    than the representation understood by the model.
+    asynchronously and should be treated as rough guidance rather than the
+    representation understood by the model.
     """
 
     instructions: Optional[str] = None
src/openai/types/beta/realtime/session_update_event.py
@@ -9,7 +9,7 @@ __all__ = [
     "SessionUpdateEvent",
     "Session",
     "SessionClientSecret",
-    "SessionClientSecretExpiresAt",
+    "SessionClientSecretExpiresAfter",
     "SessionInputAudioNoiseReduction",
     "SessionInputAudioTranscription",
     "SessionTool",
@@ -19,8 +19,8 @@ __all__ = [
 ]
 
 
-class SessionClientSecretExpiresAt(BaseModel):
-    anchor: Optional[Literal["created_at"]] = None
+class SessionClientSecretExpiresAfter(BaseModel):
+    anchor: Literal["created_at"]
     """The anchor point for the ephemeral token expiration.
 
     Only `created_at` is currently supported.
@@ -34,7 +34,7 @@ class SessionClientSecretExpiresAt(BaseModel):
 
 
 class SessionClientSecret(BaseModel):
-    expires_at: Optional[SessionClientSecretExpiresAt] = None
+    expires_after: Optional[SessionClientSecretExpiresAfter] = None
     """Configuration for the ephemeral token expiration."""
 
 
src/openai/types/beta/realtime/session_update_event_param.py
@@ -9,7 +9,7 @@ __all__ = [
     "SessionUpdateEventParam",
     "Session",
     "SessionClientSecret",
-    "SessionClientSecretExpiresAt",
+    "SessionClientSecretExpiresAfter",
     "SessionInputAudioNoiseReduction",
     "SessionInputAudioTranscription",
     "SessionTool",
@@ -19,8 +19,8 @@ __all__ = [
 ]
 
 
-class SessionClientSecretExpiresAt(TypedDict, total=False):
-    anchor: Literal["created_at"]
+class SessionClientSecretExpiresAfter(TypedDict, total=False):
+    anchor: Required[Literal["created_at"]]
     """The anchor point for the ephemeral token expiration.
 
     Only `created_at` is currently supported.
@@ -34,7 +34,7 @@ class SessionClientSecretExpiresAt(TypedDict, total=False):
 
 
 class SessionClientSecret(TypedDict, total=False):
-    expires_at: SessionClientSecretExpiresAt
+    expires_after: SessionClientSecretExpiresAfter
     """Configuration for the ephemeral token expiration."""
 
 
src/openai/types/fine_tuning/checkpoints/permission_retrieve_response.py
@@ -1,13 +1,14 @@
 # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
 
+from typing import List, Optional
 from typing_extensions import Literal
 
 from ...._models import BaseModel
 
-__all__ = ["PermissionRetrieveResponse"]
+__all__ = ["PermissionRetrieveResponse", "Data"]
 
 
-class PermissionRetrieveResponse(BaseModel):
+class Data(BaseModel):
     id: str
     """The permission identifier, which can be referenced in the API endpoints."""
 
@@ -19,3 +20,15 @@ class PermissionRetrieveResponse(BaseModel):
 
     project_id: str
     """The project identifier that the permission is for."""
+
+
+class PermissionRetrieveResponse(BaseModel):
+    data: List[Data]
+
+    has_more: bool
+
+    object: Literal["list"]
+
+    first_id: Optional[str] = None
+
+    last_id: Optional[str] = None
src/openai/types/responses/response_code_interpreter_call_code_delta_event.py
@@ -9,13 +9,19 @@ __all__ = ["ResponseCodeInterpreterCallCodeDeltaEvent"]
 
 class ResponseCodeInterpreterCallCodeDeltaEvent(BaseModel):
     delta: str
-    """The partial code snippet added by the code interpreter."""
+    """The partial code snippet being streamed by the code interpreter."""
+
+    item_id: str
+    """The unique identifier of the code interpreter tool call item."""
 
     output_index: int
-    """The index of the output item that the code interpreter call is in progress."""
+    """
+    The index of the output item in the response for which the code is being
+    streamed.
+    """
 
     sequence_number: int
-    """The sequence number of this event."""
+    """The sequence number of this event, used to order streaming events."""
 
     type: Literal["response.code_interpreter_call_code.delta"]
     """The type of the event. Always `response.code_interpreter_call_code.delta`."""
src/openai/types/responses/response_code_interpreter_call_code_done_event.py
@@ -11,11 +11,14 @@ class ResponseCodeInterpreterCallCodeDoneEvent(BaseModel):
     code: str
     """The final code snippet output by the code interpreter."""
 
+    item_id: str
+    """The unique identifier of the code interpreter tool call item."""
+
     output_index: int
-    """The index of the output item that the code interpreter call is in progress."""
+    """The index of the output item in the response for which the code is finalized."""
 
     sequence_number: int
-    """The sequence number of this event."""
+    """The sequence number of this event, used to order streaming events."""
 
     type: Literal["response.code_interpreter_call_code.done"]
     """The type of the event. Always `response.code_interpreter_call_code.done`."""
src/openai/types/responses/response_code_interpreter_call_completed_event.py
@@ -3,20 +3,22 @@
 from typing_extensions import Literal
 
 from ..._models import BaseModel
-from .response_code_interpreter_tool_call import ResponseCodeInterpreterToolCall
 
 __all__ = ["ResponseCodeInterpreterCallCompletedEvent"]
 
 
 class ResponseCodeInterpreterCallCompletedEvent(BaseModel):
-    code_interpreter_call: ResponseCodeInterpreterToolCall
-    """A tool call to run code."""
+    item_id: str
+    """The unique identifier of the code interpreter tool call item."""
 
     output_index: int
-    """The index of the output item that the code interpreter call is in progress."""
+    """
+    The index of the output item in the response for which the code interpreter call
+    is completed.
+    """
 
     sequence_number: int
-    """The sequence number of this event."""
+    """The sequence number of this event, used to order streaming events."""
 
     type: Literal["response.code_interpreter_call.completed"]
     """The type of the event. Always `response.code_interpreter_call.completed`."""
src/openai/types/responses/response_code_interpreter_call_in_progress_event.py
@@ -3,20 +3,22 @@
 from typing_extensions import Literal
 
 from ..._models import BaseModel
-from .response_code_interpreter_tool_call import ResponseCodeInterpreterToolCall
 
 __all__ = ["ResponseCodeInterpreterCallInProgressEvent"]
 
 
 class ResponseCodeInterpreterCallInProgressEvent(BaseModel):
-    code_interpreter_call: ResponseCodeInterpreterToolCall
-    """A tool call to run code."""
+    item_id: str
+    """The unique identifier of the code interpreter tool call item."""
 
     output_index: int
-    """The index of the output item that the code interpreter call is in progress."""
+    """
+    The index of the output item in the response for which the code interpreter call
+    is in progress.
+    """
 
     sequence_number: int
-    """The sequence number of this event."""
+    """The sequence number of this event, used to order streaming events."""
 
     type: Literal["response.code_interpreter_call.in_progress"]
     """The type of the event. Always `response.code_interpreter_call.in_progress`."""
src/openai/types/responses/response_code_interpreter_call_interpreting_event.py
@@ -3,20 +3,22 @@
 from typing_extensions import Literal
 
 from ..._models import BaseModel
-from .response_code_interpreter_tool_call import ResponseCodeInterpreterToolCall
 
 __all__ = ["ResponseCodeInterpreterCallInterpretingEvent"]
 
 
 class ResponseCodeInterpreterCallInterpretingEvent(BaseModel):
-    code_interpreter_call: ResponseCodeInterpreterToolCall
-    """A tool call to run code."""
+    item_id: str
+    """The unique identifier of the code interpreter tool call item."""
 
     output_index: int
-    """The index of the output item that the code interpreter call is in progress."""
+    """
+    The index of the output item in the response for which the code interpreter is
+    interpreting code.
+    """
 
     sequence_number: int
-    """The sequence number of this event."""
+    """The sequence number of this event, used to order streaming events."""
 
     type: Literal["response.code_interpreter_call.interpreting"]
     """The type of the event. Always `response.code_interpreter_call.interpreting`."""
src/openai/types/responses/response_code_interpreter_tool_call.py
@@ -6,50 +6,46 @@ from typing_extensions import Literal, Annotated, TypeAlias
 from ..._utils import PropertyInfo
 from ..._models import BaseModel
 
-__all__ = ["ResponseCodeInterpreterToolCall", "Result", "ResultLogs", "ResultFiles", "ResultFilesFile"]
+__all__ = ["ResponseCodeInterpreterToolCall", "Output", "OutputLogs", "OutputImage"]
 
 
-class ResultLogs(BaseModel):
+class OutputLogs(BaseModel):
     logs: str
-    """The logs of the code interpreter tool call."""
+    """The logs output from the code interpreter."""
 
     type: Literal["logs"]
-    """The type of the code interpreter text output. Always `logs`."""
+    """The type of the output. Always 'logs'."""
 
 
-class ResultFilesFile(BaseModel):
-    file_id: str
-    """The ID of the file."""
+class OutputImage(BaseModel):
+    type: Literal["image"]
+    """The type of the output. Always 'image'."""
 
-    mime_type: str
-    """The MIME type of the file."""
+    url: str
+    """The URL of the image output from the code interpreter."""
 
 
-class ResultFiles(BaseModel):
-    files: List[ResultFilesFile]
-
-    type: Literal["files"]
-    """The type of the code interpreter file output. Always `files`."""
-
-
-Result: TypeAlias = Annotated[Union[ResultLogs, ResultFiles], PropertyInfo(discriminator="type")]
+Output: TypeAlias = Annotated[Union[OutputLogs, OutputImage], PropertyInfo(discriminator="type")]
 
 
 class ResponseCodeInterpreterToolCall(BaseModel):
     id: str
     """The unique ID of the code interpreter tool call."""
 
-    code: str
-    """The code to run."""
+    code: Optional[str] = None
+    """The code to run, or null if not available."""
+
+    container_id: str
+    """The ID of the container used to run the code."""
+
+    outputs: Optional[List[Output]] = None
+    """The outputs generated by the code interpreter, such as logs or images.
 
-    results: List[Result]
-    """The results of the code interpreter tool call."""
+    Can be null if no outputs are available.
+    """
 
-    status: Literal["in_progress", "interpreting", "completed"]
+    status: Literal["in_progress", "completed", "incomplete", "interpreting", "failed"]
     """The status of the code interpreter tool call."""
 
     type: Literal["code_interpreter_call"]
     """The type of the code interpreter tool call. Always `code_interpreter_call`."""
-
-    container_id: Optional[str] = None
-    """The ID of the container used to run the code."""
src/openai/types/responses/response_code_interpreter_tool_call_param.py
@@ -2,53 +2,49 @@
 
 from __future__ import annotations
 
-from typing import Union, Iterable
+from typing import Union, Iterable, Optional
 from typing_extensions import Literal, Required, TypeAlias, TypedDict
 
-__all__ = ["ResponseCodeInterpreterToolCallParam", "Result", "ResultLogs", "ResultFiles", "ResultFilesFile"]
+__all__ = ["ResponseCodeInterpreterToolCallParam", "Output", "OutputLogs", "OutputImage"]
 
 
-class ResultLogs(TypedDict, total=False):
+class OutputLogs(TypedDict, total=False):
     logs: Required[str]
-    """The logs of the code interpreter tool call."""
+    """The logs output from the code interpreter."""
 
     type: Required[Literal["logs"]]
-    """The type of the code interpreter text output. Always `logs`."""
+    """The type of the output. Always 'logs'."""
 
 
-class ResultFilesFile(TypedDict, total=False):
-    file_id: Required[str]
-    """The ID of the file."""
+class OutputImage(TypedDict, total=False):
+    type: Required[Literal["image"]]
+    """The type of the output. Always 'image'."""
 
-    mime_type: Required[str]
-    """The MIME type of the file."""
+    url: Required[str]
+    """The URL of the image output from the code interpreter."""
 
 
-class ResultFiles(TypedDict, total=False):
-    files: Required[Iterable[ResultFilesFile]]
-
-    type: Required[Literal["files"]]
-    """The type of the code interpreter file output. Always `files`."""
-
-
-Result: TypeAlias = Union[ResultLogs, ResultFiles]
+Output: TypeAlias = Union[OutputLogs, OutputImage]
 
 
 class ResponseCodeInterpreterToolCallParam(TypedDict, total=False):
     id: Required[str]
     """The unique ID of the code interpreter tool call."""
 
-    code: Required[str]
-    """The code to run."""
+    code: Required[Optional[str]]
+    """The code to run, or null if not available."""
+
+    container_id: Required[str]
+    """The ID of the container used to run the code."""
+
+    outputs: Required[Optional[Iterable[Output]]]
+    """The outputs generated by the code interpreter, such as logs or images.
 
-    results: Required[Iterable[Result]]
-    """The results of the code interpreter tool call."""
+    Can be null if no outputs are available.
+    """
 
-    status: Required[Literal["in_progress", "interpreting", "completed"]]
+    status: Required[Literal["in_progress", "completed", "incomplete", "interpreting", "failed"]]
     """The status of the code interpreter tool call."""
 
     type: Required[Literal["code_interpreter_call"]]
     """The type of the code interpreter tool call. Always `code_interpreter_call`."""
-
-    container_id: str
-    """The ID of the container used to run the code."""
src/openai/types/responses/response_output_text.py
@@ -22,6 +22,9 @@ class AnnotationFileCitation(BaseModel):
     file_id: str
     """The ID of the file."""
 
+    filename: str
+    """The filename of the file cited."""
+
     index: int
     """The index of the file in the list of files."""
 
@@ -56,6 +59,9 @@ class AnnotationContainerFileCitation(BaseModel):
     file_id: str
     """The ID of the file."""
 
+    filename: str
+    """The filename of the container file cited."""
+
     start_index: int
     """The index of the first character of the container file citation in the message."""
 
src/openai/types/responses/response_output_text_param.py
@@ -21,6 +21,9 @@ class AnnotationFileCitation(TypedDict, total=False):
     file_id: Required[str]
     """The ID of the file."""
 
+    filename: Required[str]
+    """The filename of the file cited."""
+
     index: Required[int]
     """The index of the file in the list of files."""
 
@@ -55,6 +58,9 @@ class AnnotationContainerFileCitation(TypedDict, total=False):
     file_id: Required[str]
     """The ID of the file."""
 
+    filename: Required[str]
+    """The filename of the container file cited."""
+
     start_index: Required[int]
     """The index of the first character of the container file citation in the message."""
 
src/openai/_version.py
@@ -1,4 +1,4 @@
 # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
 
 __title__ = "openai"
-__version__ = "1.90.0"  # x-release-please-version
+__version__ = "1.91.0"  # x-release-please-version
tests/api_resources/audio/test_speech.py
@@ -44,6 +44,7 @@ class TestSpeech:
             instructions="instructions",
             response_format="mp3",
             speed=0.25,
+            stream_format="sse",
         )
         assert isinstance(speech, _legacy_response.HttpxBinaryResponseContent)
         assert speech.json() == {"foo": "bar"}
@@ -110,6 +111,7 @@ class TestAsyncSpeech:
             instructions="instructions",
             response_format="mp3",
             speed=0.25,
+            stream_format="sse",
         )
         assert isinstance(speech, _legacy_response.HttpxBinaryResponseContent)
         assert speech.json() == {"foo": "bar"}
tests/api_resources/beta/realtime/test_sessions.py
@@ -26,7 +26,7 @@ class TestSessions:
     def test_method_create_with_all_params(self, client: OpenAI) -> None:
         session = client.beta.realtime.sessions.create(
             client_secret={
-                "expires_at": {
+                "expires_after": {
                     "anchor": "created_at",
                     "seconds": 0,
                 }
@@ -103,7 +103,7 @@ class TestAsyncSessions:
     async def test_method_create_with_all_params(self, async_client: AsyncOpenAI) -> None:
         session = await async_client.beta.realtime.sessions.create(
             client_secret={
-                "expires_at": {
+                "expires_after": {
                     "anchor": "created_at",
                     "seconds": 0,
                 }
tests/api_resources/fine_tuning/checkpoints/test_permissions.py
@@ -9,7 +9,7 @@ import pytest
 
 from openai import OpenAI, AsyncOpenAI
 from tests.utils import assert_matches_type
-from openai.pagination import SyncPage, AsyncPage, SyncCursorPage, AsyncCursorPage
+from openai.pagination import SyncPage, AsyncPage
 from openai.types.fine_tuning.checkpoints import (
     PermissionCreateResponse,
     PermissionDeleteResponse,
@@ -71,7 +71,7 @@ class TestPermissions:
         permission = client.fine_tuning.checkpoints.permissions.retrieve(
             fine_tuned_model_checkpoint="ft-AF1WoRqd3aJAHsqc9NY7iL8F",
         )
-        assert_matches_type(SyncCursorPage[PermissionRetrieveResponse], permission, path=["response"])
+        assert_matches_type(PermissionRetrieveResponse, permission, path=["response"])
 
     @parametrize
     def test_method_retrieve_with_all_params(self, client: OpenAI) -> None:
@@ -82,7 +82,7 @@ class TestPermissions:
             order="ascending",
             project_id="project_id",
         )
-        assert_matches_type(SyncCursorPage[PermissionRetrieveResponse], permission, path=["response"])
+        assert_matches_type(PermissionRetrieveResponse, permission, path=["response"])
 
     @parametrize
     def test_raw_response_retrieve(self, client: OpenAI) -> None:
@@ -93,7 +93,7 @@ class TestPermissions:
         assert response.is_closed is True
         assert response.http_request.headers.get("X-Stainless-Lang") == "python"
         permission = response.parse()
-        assert_matches_type(SyncCursorPage[PermissionRetrieveResponse], permission, path=["response"])
+        assert_matches_type(PermissionRetrieveResponse, permission, path=["response"])
 
     @parametrize
     def test_streaming_response_retrieve(self, client: OpenAI) -> None:
@@ -104,7 +104,7 @@ class TestPermissions:
             assert response.http_request.headers.get("X-Stainless-Lang") == "python"
 
             permission = response.parse()
-            assert_matches_type(SyncCursorPage[PermissionRetrieveResponse], permission, path=["response"])
+            assert_matches_type(PermissionRetrieveResponse, permission, path=["response"])
 
         assert cast(Any, response.is_closed) is True
 
@@ -222,7 +222,7 @@ class TestAsyncPermissions:
         permission = await async_client.fine_tuning.checkpoints.permissions.retrieve(
             fine_tuned_model_checkpoint="ft-AF1WoRqd3aJAHsqc9NY7iL8F",
         )
-        assert_matches_type(AsyncCursorPage[PermissionRetrieveResponse], permission, path=["response"])
+        assert_matches_type(PermissionRetrieveResponse, permission, path=["response"])
 
     @parametrize
     async def test_method_retrieve_with_all_params(self, async_client: AsyncOpenAI) -> None:
@@ -233,7 +233,7 @@ class TestAsyncPermissions:
             order="ascending",
             project_id="project_id",
         )
-        assert_matches_type(AsyncCursorPage[PermissionRetrieveResponse], permission, path=["response"])
+        assert_matches_type(PermissionRetrieveResponse, permission, path=["response"])
 
     @parametrize
     async def test_raw_response_retrieve(self, async_client: AsyncOpenAI) -> None:
@@ -244,7 +244,7 @@ class TestAsyncPermissions:
         assert response.is_closed is True
         assert response.http_request.headers.get("X-Stainless-Lang") == "python"
         permission = response.parse()
-        assert_matches_type(AsyncCursorPage[PermissionRetrieveResponse], permission, path=["response"])
+        assert_matches_type(PermissionRetrieveResponse, permission, path=["response"])
 
     @parametrize
     async def test_streaming_response_retrieve(self, async_client: AsyncOpenAI) -> None:
@@ -255,7 +255,7 @@ class TestAsyncPermissions:
             assert response.http_request.headers.get("X-Stainless-Lang") == "python"
 
             permission = await response.parse()
-            assert_matches_type(AsyncCursorPage[PermissionRetrieveResponse], permission, path=["response"])
+            assert_matches_type(PermissionRetrieveResponse, permission, path=["response"])
 
         assert cast(Any, response.is_closed) is True
 
.release-please-manifest.json
@@ -1,3 +1,3 @@
 {
-  ".": "1.90.0"
+  ".": "1.91.0"
 }
\ No newline at end of file
.stats.yml
@@ -1,4 +1,4 @@
 configured_endpoints: 111
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai%2Fopenai-f411a68f272b8be0ab0c266043da33228687b9b2d76896724e3cef797de9563d.yml
-openapi_spec_hash: 89bf866ea95ecfb3d76c8833237047d6
-config_hash: dc5515e257676a27cb1ace1784aa92b3
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai%2Fopenai-ef4ecb19eb61e24c49d77fef769ee243e5279bc0bdbaee8d0f8dba4da8722559.yml
+openapi_spec_hash: 1b8a9767c9f04e6865b06c41948cdc24
+config_hash: fd2af1d5eff0995bb7dc02ac9a34851d
api.md
@@ -293,7 +293,7 @@ from openai.types.fine_tuning.checkpoints import (
 Methods:
 
 - <code title="post /fine_tuning/checkpoints/{fine_tuned_model_checkpoint}/permissions">client.fine_tuning.checkpoints.permissions.<a href="./src/openai/resources/fine_tuning/checkpoints/permissions.py">create</a>(fine_tuned_model_checkpoint, \*\*<a href="src/openai/types/fine_tuning/checkpoints/permission_create_params.py">params</a>) -> <a href="./src/openai/types/fine_tuning/checkpoints/permission_create_response.py">SyncPage[PermissionCreateResponse]</a></code>
-- <code title="get /fine_tuning/checkpoints/{fine_tuned_model_checkpoint}/permissions">client.fine_tuning.checkpoints.permissions.<a href="./src/openai/resources/fine_tuning/checkpoints/permissions.py">retrieve</a>(fine_tuned_model_checkpoint, \*\*<a href="src/openai/types/fine_tuning/checkpoints/permission_retrieve_params.py">params</a>) -> <a href="./src/openai/types/fine_tuning/checkpoints/permission_retrieve_response.py">SyncCursorPage[PermissionRetrieveResponse]</a></code>
+- <code title="get /fine_tuning/checkpoints/{fine_tuned_model_checkpoint}/permissions">client.fine_tuning.checkpoints.permissions.<a href="./src/openai/resources/fine_tuning/checkpoints/permissions.py">retrieve</a>(fine_tuned_model_checkpoint, \*\*<a href="src/openai/types/fine_tuning/checkpoints/permission_retrieve_params.py">params</a>) -> <a href="./src/openai/types/fine_tuning/checkpoints/permission_retrieve_response.py">PermissionRetrieveResponse</a></code>
 - <code title="delete /fine_tuning/checkpoints/{fine_tuned_model_checkpoint}/permissions/{permission_id}">client.fine_tuning.checkpoints.permissions.<a href="./src/openai/resources/fine_tuning/checkpoints/permissions.py">delete</a>(permission_id, \*, fine_tuned_model_checkpoint) -> <a href="./src/openai/types/fine_tuning/checkpoints/permission_delete_response.py">PermissionDeleteResponse</a></code>
 
 ## Alpha
CHANGELOG.md
@@ -1,5 +1,13 @@
 # Changelog
 
+## 1.91.0 (2025-06-23)
+
+Full Changelog: [v1.90.0...v1.91.0](https://github.com/openai/openai-python/compare/v1.90.0...v1.91.0)
+
+### Features
+
+* **api:** update api shapes for usage and code interpreter ([060d566](https://github.com/openai/openai-python/commit/060d5661e4a1fcdb953c52facd3e668ee80f9295))
+
 ## 1.90.0 (2025-06-20)
 
 Full Changelog: [v1.89.0...v1.90.0](https://github.com/openai/openai-python/compare/v1.89.0...v1.90.0)
pyproject.toml
@@ -1,6 +1,6 @@
 [project]
 name = "openai"
-version = "1.90.0"
+version = "1.91.0"
 description = "The official Python library for the openai API"
 dynamic = ["readme"]
 license = "Apache-2.0"