{
  "$type": "site.standard.document",
  "bskyPostRef": {
    "cid": "bafyreiaodaprendnynncjeh6b7gbqxufqdgvcy3anl7qr6hluj64qnu7jy",
    "uri": "at://did:plc:lk3jfj3zq4k4wxnk474axylu/app.bsky.feed.post/3mhuu6svao3t2"
  },
  "path": "/t/cancelling-stream-does-not-show-usage/1377768#post_1",
  "publishedAt": "2026-03-25T09:42:28.000Z",
  "site": "https://community.openai.com",
  "textContent": "When we cancel a stream OpenAI does not tell us how much it was charged. See this example code:\n\n\n    import asyncio\n    import base64\n    from pathlib import Path\n\n    from openai import AsyncOpenAI\n\n    from utils.storage_utils import get_mime_type\n\n    MAX_CHUNKS = 20\n\n\n    async def main():\n        client = AsyncOpenAI()\n        pdf_path = Path(__file__).parent / \"test.pdf\"\n        pdf_bytes = pdf_path.read_bytes()\n        filename = pdf_path.name\n\n        file_content = [\n            {\n                \"type\": \"input_file\",\n                \"filename\": filename,\n                \"file_data\": f\"data:{get_mime_type(filename)};base64,{base64.b64encode(pdf_bytes).decode()}\",\n            }\n        ]\n\n        stream = await client.responses.create(\n            model=\"gpt-5-mini\",\n            input=[{\"role\": \"user\", \"content\": file_content + [{\"type\": \"input_text\", \"text\": \"Can you summarise this file?\"}]}],\n            stream=True,\n            background=True,\n        )\n\n        response_id = None\n        chunk_count = 0\n\n        async for event in stream:\n            if event.type == \"response.created\":\n                response_id = event.response.id\n                print(f\"Response ID: {response_id}\\n\")\n\n            elif event.type == \"response.output_text.delta\":\n                print(event.delta, end=\"\", flush=True)\n                chunk_count += 1\n\n                if chunk_count >= MAX_CHUNKS:\n                    print(f\"\\n\\n--- cancelling after {chunk_count} chunks ---\\n\")\n                    cancelled = await client.responses.cancel(response_id)\n                    print(f\"[cancel]    status: {cancelled.status}\")\n                    print(f\"[cancel]    usage:  {cancelled.usage}\")\n                    break\n\n            elif event.type == \"response.completed\":\n                print(f\"\\n[stream]    status: {event.response.status}\")\n                print(f\"[stream]    usage:  {event.response.usage}\")\n\n        await stream.close()\n\n        if response_id:\n            result = await client.responses.retrieve(response_id)\n            print(f\"\\n[retrieve]  status: {result.status}\")\n            print(f\"[retrieve]  usage:  {result.usage}\")\n\n\n    if __name__ == \"__main__\":\n        asyncio.run(main())\n\n\nThe output is:\n\n\n    Response ID: resp_*\n\n    Here’s a concise summary of the acta (hearing minutes):\n\n    - Court and process\n\n\n    --- cancelling after 20 chunks ---\n\n    [cancel]    status: cancelled\n    [cancel]    usage:  None\n\n    [retrieve]  status: cancelled\n    [retrieve]  usage:  None\n",
  "title": "Cancelling Stream Does Not Show Usage"
}