SpyBara
Go Premium

Documentation 2026-10-27 23:58 UTC to 2026-10-28 23:00 UTC

9 files changed +397 −57. View all changes and history on the product overview
2026
Sat 31 23:01 Fri 30 23:59 Thu 29 23:59 Wed 28 23:00 Tue 27 23:58 Mon 26 23:58 Sat 24 23:02 Fri 23 23:58 Thu 22 22:59 Wed 21 23:02 Tue 20 23:02 Mon 19 23:00 Sun 18 23:00 Sat 17 22:57 Fri 16 23:02 Thu 15 23:00 Wed 14 23:59 Tue 13 23:00 Sun 11 23:59 Sat 10 23:58 Fri 9 22:57 Thu 8 23:01 Wed 7 23:57 Tue 6 22:58 Mon 5 22:59 Sun 4 22:58 Fri 2 23:58 Thu 1 22:59

guides/chatgpt-api-credits.md +115 −0 created

Details

1# API credits for ChatGPT subscribers

2 

3> For the complete documentation index, see [llms.txt](/llms.txt). Markdown versions of documentation pages are available by appending `.md` to the page URL.

4 

5Eligible ChatGPT Pro and Business subscriptions can claim free API credits as part of their subscription benefits. Activate the benefit by linking your subscription to an API organization you own, then use the credits to build apps and agents with the OpenAI API.

6 

7- **Up to $500 per month:** Your allowance depends on your Pro plan or your Business workspace’s paid seats.

8- **Activate once:** Receive credits automatically when your subscription renews, while these benefits are available and your subscription is eligible.

9- **Use them before your billing cycle ends:** Unused credits expire at the end of the billing cycle and don't roll over.

10- **No API payment method required:** You can use the API with active free credits.

11 

12The benefit is subject to [API terms](https://openai.com/policies/service-credit-terms/) and [policies](https://openai.com/policies/usage-policies/) including [API rate limits](https://developers.openai.com/api/docs/guides/rate-limits). Check the limits for your organization and models in [organization limits](https://platform.openai.com/settings/organization/limits).

13 

14## Credit amounts

15 

16| ChatGPT subscription | Monthly API credits (USD) |

17| -------------------- | -------------------------- |

18| Pro ($100 tier) | $100 |

19| Pro ($200 tier) | $200 |

20| Pro ($500 tier) | $500 |

21| Business Standard | $20 per paid Standard seat |

22| Business Premium | $100 per paid Premium seat |

23 

24Your first grant is prorated for the time left in your current subscription billing cycle and expires at the end of that billing cycle.

25 

26Business API Credits are pooled and capped at $500 per workspace per month. Business workspaces that pay annually upfront receive the full year’s grant in one issuance, and the grant expires at the end of the annual billing cycle.

27 

28## Eligibility

29 

30To claim the benefit:

31 

32- Have an active, paid ChatGPT Pro or Business subscription that is at least seven days old. Free trials and complimentary subscriptions don't qualify.

33- Be an owner of the ChatGPT subscription or Business workspace and an owner of the API organization receiving the credits.

34- Use the same email address for your ChatGPT account and the API account used to link the organization.

35 

36## Claim your credits

37 

38Choose where to start. Both paths link the same subscription benefit to your selected API organization.

39 

40If you’re new to the API, you will be able to link your subscription to your Personal API Organization. Use the email address associated with your eligible ChatGPT subscription.

41 

42 

43 

44

45 

46 

471. Sign in to [**ChatGPT**](https://chatgpt.com/) with the account that owns the eligible subscription.

482. For Pro, open [**Settings → Billing**](https://chatgpt.com/settings/billing). For Business, open your workspace’s billing settings in ChatGPT or the [**Admin Console**](https://admin.openai.com/).

493. Find the API credits benefit and start the claim flow.

504. Review the API organization that will receive the credits. If you own multiple eligible organizations, select the one you would like to link.

515. Confirm to activate the benefit.

52 

53

54 

55

56 

57 

581. Sign in to [**API Platform**](https://platform.openai.com/) with the email address associated with your eligible ChatGPT subscription.

592. Select the API organization you own that should receive the credits.

603. Open [**Billing**](https://platform.openai.com/settings/organization/billing/) and find the API credit benefit.

614. Select the eligible ChatGPT subscription or Business workspace you own to link.

625. Confirm to activate the benefit.

63 

64

65 

66 

67 

68 

69After claiming, open [API Platform billing settings](https://platform.openai.com/settings/organization/billing/overview) to see your credits. Now, you're ready to start building with the API!

70 

71- Follow the [**API quickstart**](https://developers.openai.com/api/docs/quickstart) to make your first request.

72- Build an agent with the [Agents API](https://platform.openai.com/agents).

73- Start building and testing prompts in the [Responses](https://platform.openai.com/chat/), [Decisions](https://platform.openai.com/decisions), and [Audio](https://platform.openai.com/audio/live) playgrounds.

74- Track usage in the [**Usage dashboard**](https://platform.openai.com/usage).

75- Use the [**OpenAI Developers Plugin**](https://chatgpt.com/plugins/openai-developers?open_in_app) in ChatGPT to build with the API, securely create API keys directly in ChatGPT, and build together with the API and ChatGPT Sites.

76 

77## What the credits cover

78 

79These benefits cover paid API Platform usage billed to the linked organization, including:

80 

81- **[Responses API](https://developers.openai.com/api/docs/guides/text)** for text, code, and image understanding.

82- **[Agents API](https://developers.openai.com/api/docs/guides/agents-api/overview)** for running agents, including OpenAI-hosted sandbox charges.

83- **[Decisions API](https://developers.openai.com/api/docs/guides/decisions)** for structured decisions.

84- **[GPT-Live](https://developers.openai.com/api/docs/guides/live)** and the **[Realtime API](https://developers.openai.com/api/docs/guides/realtime)** for real-time voice interactions.

85- **[Images API](https://developers.openai.com/api/docs/guides/image-generation)** for image generation and editing.

86- **[Built-in tools](https://developers.openai.com/api/docs/guides/tools)** and their associated usage and storage charges, such as web search, file search, and Code Interpreter.

87- Other APIs are available through [API Platform](https://platform.openai.com).

88 

89Codex usage through API keys is not supported by this benefit. These API

90 credits also don't increase your ChatGPT or signed-in Codex usage limits.

91 

92## When your free credits run out

93 

94Your organization uses free API credits before purchased API credits. When your free API credit balance runs out:

95 

96| Organization balance | What happens |

97| ---------------------------- | ---------------------------------------------------------------------------- |

98| Purchased API credits remain | API usage continues using your purchased credits. |

99| No credits remain | API requests fail with HTTP `429` and error code `credit_balance_exhausted`. |

100 

101To continue when no credits remain:

102 

103- Add paid API credits in your organization’s [**billing settings**](https://platform.openai.com/settings/organization/billing/overview).

104- Set up Auto Recharge to add paid credits to continue building without errors and interruptions.

105 

106## More about this benefit

107 

108- **Organization-specific credits:** Grants apply only to the linked API organization. Select that organization and use one of its project API keys when making requests.

109- **Subscription changes:** Upgrading your Pro plan can provide extra prorated credits for the rest of the billing cycle. Later grants reflect the eligible plan's allowance, up to $500 per billing cycle.

110- **Business seat changes:** Adding paid seats or upgrading seat types during a billing cycle can provide extra prorated credits, subject to a shared workspace cap of $500 per monthly billing cycle or $6,000 per annual billing cycle. Seat reductions affect the next billing cycle. Reassigning an existing seat to another person doesn't create extra credits.

111- **Cancellation or an ineligible plan:** New grants stop when your subscription is no longer eligible. Cancellation alone doesn't revoke credits already issued; you can use them until they expire.

112- **Downgrading to an ineligible plan:** If you downgrade to an ineligible ChatGPT plan, such as Plus, Go, or Free, your API organization link is removed at the end of the billing cycle.

113- **Moving from Pro to Business:** Moving to Business ends the Pro link. After the workspace's paid subscription has been active for seven days, a Business workspace owner can create a new link to claim the Business benefit.

114- **Moving from Business to Enterprise:** If your ChatGPT Business subscription moves to ChatGPT Enterprise, your API organization link is removed at the end of the billing cycle. ChatGPT Enterprise is not eligible for this benefit.

115- **Changing the receiving organization:** Contact support if you need to change the linked API Organization.

Details

1810import OpenAI from "openai";1810import OpenAI from "openai";

1811import { ResponsesWS } from "openai/resources/responses/ws";1811import { ResponsesWS } from "openai/resources/responses/ws";

1812 1812 

1813const openai = new OpenAI();1813const testLogTool = {

1814 type: "function",

1815 name: "search_test_logs",

1816 description: "Search test logs for a query.",

1817 parameters: {

1818 type: "object",

1819 properties: { query: { type: "string" } },

1820 required: ["query"],

1821 additionalProperties: false,

1822 },

1823 strict: true,

1824};

1814 1825 

1815const ws = new ResponsesWS(openai);1826const codeSearchTool = {

1827 type: "function",

1828 name: "search_code",

1829 description: "Search the codebase for a query.",

1830 parameters: {

1831 type: "object",

1832 properties: { query: { type: "string" } },

1833 required: ["query"],

1834 additionalProperties: false,

1835 },

1836 strict: true,

1837};

1816 1838 

1817ws.on("event", (event) => {1839const openai = new OpenAI();

1818 console.log(event.type);1840const ws = new ResponsesWS(openai);

1819 if (

1820 event.type === "response.completed" ||

1821 event.type === "response.failed" ||

1822 event.type === "response.incomplete"

1823 ) {

1824 ws.close();

1825 }

1826});

1827ws.on("error", (error) => {

1828 console.error(error);

1829 ws.close();

1830});

1831 1841 

1832ws.send({1842try {

1843 ws.send({

1833 type: "response.create",1844 type: "response.create",

1834 model: "gpt-6-astra",1845 model: "gpt-6-astra",

1835 store: false,1846 store: false,


1848 },1859 },

1849 ],1860 ],

1850 tools: [testLogTool, codeSearchTool],1861 tools: [testLogTool, codeSearchTool],

1851});1862 });

1863 let completed = false;

1864 for await (const event of ws) {

1865 if (event.type === "error") throw event.error;

1866 if (event.type !== "message") continue;

1867 const message = event.message;

1868 if (message.type === "response.completed") {

1869 console.log(JSON.stringify(message.response.output));

1870 completed = true;

1871 break;

1872 }

1873 if (

1874 message.type === "response.failed" ||

1875 message.type === "response.incomplete"

1876 ) {

1877 throw new Error(JSON.stringify(message));

1878 }

1879 }

1880 if (!completed) {

1881 throw new Error("Connection closed before the response finished.");

1882 }

1883} finally {

1884 ws.close();

1885}

1852```1886```

1853 1887 

1854```python1888```python

1855from openai import OpenAI1889from openai import OpenAI

1890from openai.types.responses import FunctionToolParam

1891 

1892test_log_tool: FunctionToolParam = {

1893 "type": "function",

1894 "name": "search_test_logs",

1895 "description": "Search test logs.",

1896 "parameters": {

1897 "type": "object",

1898 "properties": {"query": {"type": "string"}},

1899 "required": ["query"],

1900 "additionalProperties": False,

1901 },

1902 "strict": True,

1903}

1904code_search_tool: FunctionToolParam = {

1905 "type": "function",

1906 "name": "search_code",

1907 "description": "Search source code.",

1908 "parameters": {

1909 "type": "object",

1910 "properties": {"query": {"type": "string"}},

1911 "required": ["query"],

1912 "additionalProperties": False,

1913 },

1914 "strict": True,

1915}

1856 1916 

1857client = OpenAI()1917client = OpenAI()

1858 1918 


1879 ],1939 ],

1880 tools=[test_log_tool, code_search_tool],1940 tools=[test_log_tool, code_search_tool],

1881 )1941 )

1882 first_event = connection.recv()1942 for event in connection:

1883 print(first_event.type)1943 if event.type == "response.completed":

1944 print(event.response.output)

1945 break

1946 if event.type in {"response.failed", "response.incomplete", "error"}:

1947 raise RuntimeError(event.to_json())

1948 else:

1949 raise RuntimeError("Connection closed before the response finished.")

1884```1950```

1885 1951 

1886```go1952```go

Details

424async function forkSession(sourceSessionId) {424async function forkSession(sourceSessionId) {

425 const ws = new ForksWS(new OpenAI(), { session_id: sourceSessionId });425 const ws = new ForksWS(new OpenAI(), { session_id: sourceSessionId });

426 let finalized = false;426 let finalized = false;

427 let closeRequested = false;

427 try {428 try {

428 for await (const event of ws) {429 for await (const event of ws) {

429 if (event.type === "open") {430 if (event.type === "open") {


435 console.log("Fork ready:", event.message.session.id);436 console.log("Fork ready:", event.message.session.id);

436 // This startup example closes the fork after confirming it is ready.437 // This startup example closes the fork after confirming it is ready.

437 ws.send({ type: "session.close" });438 ws.send({ type: "session.close" });

439 closeRequested = true;

438 } else if (event.message.type === "session.closed") {440 } else if (event.message.type === "session.closed") {

439 console.log("Final usage:", event.message.usage);441 console.log("Final usage:", event.message.usage);

442 if (!closeRequested) {

443 throw new Error("Fork ended before startup completed");

444 }

440 finalized = true;445 finalized = true;

441 break;446 break;

442 }447 }


458 with client.live.forks.connect(session_id=source_session_id) as connection:463 with client.live.forks.connect(session_id=source_session_id) as connection:

459 connection.session.start(session={})464 connection.session.start(session={})

460 finalized = False465 finalized = False

466 close_requested = False

461 for event in connection:467 for event in connection:

462 if event.type == "session.started":468 if event.type == "session.started":

463 print("Fork ready:", event.session.id)469 print("Fork ready:", event.session.id)

464 # This startup example closes the fork after confirming it is ready.470 # This startup example closes the fork after confirming it is ready.

465 connection.session.close()471 connection.session.close()

472 close_requested = True

466 elif event.type == "session.closed":473 elif event.type == "session.closed":

467 print("Final usage:", event.usage)474 print("Final usage:", event.usage)

475 if not close_requested:

476 raise RuntimeError("Fork ended before startup completed")

468 finalized = True477 finalized = True

469 break478 break

470 elif event.type == "error":479 elif event.type == "error":

Details

192 192 

193 193 

194 194 

195Connect your own AWS S3 bucket, Azure Blob container, or Google Cloud Storage bucket to an OpenAI project. Follow the setup steps for your cloud, then register and validate the connection.195Connect your own AWS S3 bucket, Azure Blob container, Google Cloud Storage bucket, or Oracle Cloud Infrastructure (OCI) Object Storage bucket to an OpenAI project. Follow the setup steps for your cloud, then register and validate the connection.

196 196 

197ZDR with PSP is enabled per project. Once enabled, the PSP policy applies to all API traffic in that project, including requests to models that do not otherwise require PSP. To use ZDR without PSP for eligible models, send those requests through a separate project configured for ZDR without PSP.197ZDR with PSP is enabled per project. Once enabled, the PSP policy applies to all API traffic in that project, including requests to models that do not otherwise require PSP. To use ZDR without PSP for eligible models, send those requests through a separate project configured for ZDR without PSP.

198 198 


205### Open storage setup in the API console205### Open storage setup in the API console

206 206 

2071. Open **Organization settings > Data controls > Data retention**, then select **Connect storage**.2071. Open **Organization settings > Data controls > Data retention**, then select **Connect storage**.

2082. In **Connect external storage**, choose **AWS**, **Azure**, or **GCP** and select your project. You can also open **Connect storage** from **Project Settings > Data retention**.2082. In **Connect external storage**, choose **AWS**, **Azure**, **GCP**, or **OCI** and select your project. You can also open **Connect storage** from **Project Settings > Data retention**.

2093. Complete the cloud setup below. Then enter your storage details in the modal and select **Connect and validate**.2093. Complete the cloud setup below. Then enter your storage details in the modal and select **Connect and validate**.

210 210 

211### Cloud-specific Setups211### Cloud-specific Setups


220 220 

221 221 

222 222 

223Complete these steps if you're using AWS. For other clouds, skip to **Azure Blob Storage** or **Google Cloud Storage**.223Complete these steps if you're using AWS. For other clouds, skip to **Azure Blob Storage**, **Google Cloud Storage**, or **OCI Object Storage**.

224 224 

225<figure>225<figure>

226 <video226 <video


507 507 

508 508 

509 509 

510 

511 

512<a id="oci-object-storage"></a>

513 

514 

515 

516#### OCI Object Storage

517 

518 

519 

520#### 1. Create the bucket

521 

522In the OCI Console, open **Storage > Object Storage & Archive Storage > Buckets** and create a dedicated bucket. Choose a commercial region from this table that matches your project's data residency:

523 

524| Geography | Supported OCI regions |

525| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |

526| US | `us-ashburn-1`, `us-chicago-1`, `us-phoenix-1`, `us-sanjose-1` |

527| EU | `eu-amsterdam-1`, `eu-frankfurt-1`, `eu-madrid-1`, `eu-madrid-3`, `eu-marseille-1`, `eu-milan-1`, `eu-paris-1`, `eu-stockholm-1`, `eu-turin-1`, `eu-zurich-1` |

528 

529Use these bucket settings:

530 

531- **Storage tier:** Standard

532- **Visibility:** Private

533- **Object versioning:** Disabled

534- **Auto-tiering:** Disabled

535 

536Keep replication disabled. Record the bucket name and region identifier as `CUSTOMER_BUCKET_NAME` and `CUSTOMER_OCI_REGION`. Open **Profile**, select **Tenancy** followed by your tenancy's name, and copy its OCID as `CUSTOMER_TENANCY_OCID`. Your tenancy must be subscribed to the bucket's region.

537 

538#### 2. Add the bucket tags

539 

540Add these tags during bucket creation, or open the bucket's **Tags** tab and select **Add**. Set **Namespace** to **None (freeform tag)** and use your exact OpenAI organization and project IDs:

541 

542| Key | Value |

543| ------------------------ | --------------------- |

544| `openai_organization_id` | `CUSTOMER_ORG_ID` |

545| `openai_project_id` | `CUSTOMER_PROJECT_ID` |

546 

547Use the same IDs in the access policy and storage registration. Each bucket is bound to one OpenAI organization and project.

548 

549![OCI bucket creation form showing the openai_organization_id and openai_project_id freeform tags with example values.](https://developers.openai.com/images/platform/guides/private-safety-processing/setup-oci-bucket-tags.webp)

550 

551#### 3. Grant OpenAI access

552 

553In **Identity & Security > Policies**, select your tenancy's root compartment and create a policy named `psp-storage-access`. Turn on **Show manual editor** and enter these statements with your bucket name, region, and OpenAI organization and project IDs in the `CUSTOMER_...` placeholders. Keep OpenAI's tenancy and group OCIDs unchanged.

554 

555```text

556Define tenancy OpenAICSG as ocid1.tenancy.oc1..aaaaaaaa4kzwe5jdr4gsxft7dfnwbnp3aozhxeskabsqo7czdkbp6fkh3uha

557Define group OpenAICSGProduction as ocid1.group.oc1..aaaaaaaanuot5i5kooasr6qh6qo4ohqljrrxx3javkl2tkedb7ljsluq62sa

558Admit group OpenAICSGProduction of tenancy OpenAICSG to {OBJECTSTORAGE_NAMESPACE_READ} in tenancy

559Admit group OpenAICSGProduction of tenancy OpenAICSG to {BUCKET_READ} in tenancy where target.bucket.name = 'CUSTOMER_BUCKET_NAME'

560Admit group OpenAICSGProduction of tenancy OpenAICSG to {OBJECT_READ, OBJECT_CREATE, OBJECT_OVERWRITE} in tenancy where all {target.bucket.name = 'CUSTOMER_BUCKET_NAME', target.object.name = 'openai/CUSTOMER_ORG_ID/CUSTOMER_PROJECT_ID/*'}

561Allow service objectstorage-CUSTOMER_OCI_REGION to {BUCKET_INSPECT, BUCKET_READ, OBJECT_INSPECT, OBJECT_DELETE} in tenancy where target.bucket.name = 'CUSTOMER_BUCKET_NAME'

562```

563 

564The policy lets OpenAI look up your Object Storage namespace, read bucket configuration, and read and write objects under your project's prefix. Namespace lookup requires the tenancy-level permission without a bucket condition. The last statement lets Oracle's regional Object Storage service delete expired objects; for Ashburn, the service name is `objectstorage-us-ashburn-1`.

565 

566Save the policy. OpenAI manages its credentials; you don't need to create or share an API signing key or access key.

567 

568#### 4. Set the lifecycle rule

569 

570Open the bucket's **Policies** tab. Under **Lifecycle policy rules**, select **Create rule** and use these settings:

571 

572- **Name:** `psp-retention`

573- **Target:** Objects

574- **Lifecycle action:** Delete

575- **Number of days:** 30

576 

577![OCI lifecycle rule form showing the psp-retention rule with Objects as the target and deletion after 30 days.](https://developers.openai.com/images/platform/guides/private-safety-processing/setup-oci-lifecycle-rule.webp)

578 

579Expand **Advanced options** and keep **State** set to **Enabled**. Under **Object name filters**, select **Add filter**, choose **Include by prefix**, and enter `openai/CUSTOMER_ORG_ID/CUSTOMER_PROJECT_ID/`, including the trailing slash.

580 

581![OCI lifecycle advanced options showing Enabled state and an Include by prefix filter for the OpenAI organization and project.](https://developers.openai.com/images/platform/guides/private-safety-processing/setup-oci-lifecycle-prefix.webp)

582 

583Save the rule. If OCI offers to add lifecycle permissions automatically, keep the bucket-scoped grant from step 3. Make sure no other rule deletes these objects earlier or moves them to Archive storage. A retention rule doesn't replace the lifecycle deletion rule.

584 

585Continue to **Register your storage**.

586 

587 

588 

589 

590 

510### Register your storage591### Register your storage

511 592 

512After completing the cloud setup above, use either the API console or the Management API to register and validate your storage. You only need to use one method.593After completing the cloud setup above, use either the API console or the Management API to register and validate your storage. You only need to use one method.


523 604 

524##### 2. Enter your storage details605##### 2. Enter your storage details

525 606 

526Choose **AWS**, **Azure**, or **GCP**, then select the project. If you opened the modal from project settings, that project is already selected. If **Registered storage** appears, choose **Connect new storage** to add a destination.607Choose **AWS**, **Azure**, **GCP**, or **OCI**, then select the project. If you opened the modal from project settings, that project is already selected. If **Registered storage** appears, choose **Connect new storage** to add a destination.

527 608 

528For **AWS**, enter the **Bucket ARN** and **IAM role ARN** from your cloud setup.609For **AWS**, enter the **Bucket ARN** and **IAM role ARN** from your cloud setup.

529 610 

530![Connect external storage dialog for AWS showing project selection, Bucket ARN, IAM role ARN, and Connect and validate.](https://developers.openai.com/images/platform/guides/private-safety-processing/setup-07-platform-aws-connect.webp)611<img src="https://developers.openai.com/images/platform/guides/private-safety-processing/setup-07-platform-aws-connect.webp"

612 alt="Connect external storage dialog with AWS selected, showing project selection, Bucket ARN, IAM role ARN, and Connect and validate."

613 style={{ border: 0, borderRadius: 0 }}

614/>

531 615 

532For **Azure**, enter **Tenant ID**, **Subscription ID**, **Resource group**, **Storage account name**, and **Container name**. Scroll down in the modal to complete all fields.616For **Azure**, enter **Tenant ID**, **Subscription ID**, **Resource group**, **Storage account name**, and **Container name**. Scroll down in the modal to complete all fields.

533 617 

534![Connect external storage dialog for Azure showing the project and Azure storage configuration fields.](https://developers.openai.com/images/platform/guides/private-safety-processing/setup-08-platform-azure-connect.webp)618<img src="https://developers.openai.com/images/platform/guides/private-safety-processing/setup-08-platform-azure-connect.webp"

619 alt="Connect external storage dialog with Azure selected, showing project selection, Tenant ID, Subscription ID, and Resource group."

620 style={{ border: 0, borderRadius: 0 }}

621/>

535 622 

536For **GCP**, enter **Bucket name**, **Workload identity project number**, **Workload identity pool ID**, and **Workload identity provider ID**. Scroll down in the modal to complete all fields.623For **GCP**, enter **Bucket name**, **Workload identity project number**, **Workload identity pool ID**, and **Workload identity provider ID**. Scroll down in the modal to complete all fields.

537 624 

538![Connect external storage dialog for GCP showing project selection, Bucket name, Workload identity project number, and Workload identity pool ID.](https://developers.openai.com/images/platform/guides/private-safety-processing/setup-10-platform-gcp-connect.webp)625<img src="https://developers.openai.com/images/platform/guides/private-safety-processing/setup-10-platform-gcp-connect.webp"

626 alt="Connect external storage dialog with GCP selected, showing project selection, Bucket name, and Workload identity project number."

627 style={{ border: 0, borderRadius: 0 }}

628/>

629 

630For **OCI**, enter **Tenancy OCID**, **Region**, and **Bucket name**. Use the region identifier, such as `us-ashburn-1`, and the bucket name, not its OCID or URL. OpenAI discovers the Object Storage namespace automatically. Scroll down in the modal to complete all fields.

631 

632<img src="https://developers.openai.com/images/platform/guides/private-safety-processing/setup-platform-oci-connect.webp"

633 alt="Connect external storage dialog with OCI selected, showing project selection, Tenancy OCID, and Region."

634 style={{ border: 0, borderRadius: 0 }}

635/>

539 636 

540##### 3. Connect and validate637##### 3. Connect and validate

541 638 


625 }'722 }'

626```723```

627 724 

725**OCI Object Storage**

726 

727```bash

728curl --fail-with-body -sS -X POST "$OPENAI_STORAGE_URL" \

729 -H "Authorization: Bearer $OPENAI_ADMIN_KEY" \

730 -H "OpenAI-Organization: $OPENAI_ORG_ID" \

731 -H 'Content-Type: application/json' \

732 --data-binary '{

733 "project_id": "CUSTOMER_PROJECT_ID",

734 "provider": {

735 "type": "oci",

736 "tenancy_ocid": "CUSTOMER_TENANCY_OCID",

737 "region": "CUSTOMER_OCI_REGION",

738 "bucket": "CUSTOMER_BUCKET_NAME"

739 }

740 }'

741```

742 

628The response contains an `id` beginning with `extstorage_` and `status: "pending"`. Keep the ID for validation. The API console shows **Pending validation** and leaves the project's retention policy unchanged.743The response contains an `id` beginning with `extstorage_` and `status: "pending"`. Keep the ID for validation. The API console shows **Pending validation** and leaves the project's retention policy unchanged.

629 744 

630##### 3. Verify your setup745##### 3. Verify your setup


696 811 

697#### Identify validation probes812#### Identify validation probes

698 813 

699For AWS, Azure, and GCP, validation writes test objects to your configured storage destination. Their names include `csg_validation_` followed by a random hexadecimal suffix. Each object's body contains the text `customer-storage-gateway-validation:csg_validation_<suffix>`, using the same suffix as its name. They contain no customer prompts or responses. OpenAI reads each test object using the configured access, then attempts an unauthenticated `GET` of the same object to check for public access. Private storage is expected to reject the unauthenticated request. These requests may appear in your provider's access logs, depending on your logging configuration.814For AWS, Azure, GCP, and OCI, validation writes test objects to your configured storage destination. Their names include `csg_validation_` followed by a random hexadecimal suffix. Each object's body contains the text `customer-storage-gateway-validation:csg_validation_<suffix>`, using the same suffix as its name. They contain no customer prompts or responses. OpenAI reads each test object using the configured access, then attempts an unauthenticated `GET` of the same object to check for public access. Private storage is expected to reject the unauthenticated request. These requests may appear in your provider's access logs, depending on your logging configuration.

700 815 

701For AWS, validation also checks the role's `sts:ExternalId` restriction. After successfully assuming your configured role with your project's external ID, OpenAI tests `AssumeRole` calls without an external ID and with the deliberately invalid test ID `proj_smoketest-verifier`. Both test calls are expected to return `AccessDenied`. They use the same OpenAI identity and configured role; the test ID doesn't identify another customer's project. AWS CloudTrail doesn't record these denied cross-account role-assumption attempts in your account. Keep your trust policy restricted to your real project ID; don't allow the test ID or remove the external-ID condition to make these probes succeed.816For AWS, validation also checks the role's `sts:ExternalId` restriction. After successfully assuming your configured role with your project's external ID, OpenAI tests `AssumeRole` calls without an external ID and with the deliberately invalid test ID `proj_smoketest-verifier`. Both test calls are expected to return `AccessDenied`. They use the same OpenAI identity and configured role; the test ID doesn't identify another customer's project. AWS CloudTrail doesn't record these denied cross-account role-assumption attempts in your account. Keep your trust policy restricted to your real project ID; don't allow the test ID or remove the external-ID condition to make these probes succeed.

702 817 

Details

1618 "call_id": "call_sHlR7iaFwQ2YQOqm",1618 "call_id": "call_sHlR7iaFwQ2YQOqm",

1619 "arguments": "{\"sign\":\"Aquarius\"}"1619 "arguments": "{\"sign\":\"Aquarius\"}"

1620 }1620 }

1621 ],1621 ]

1622 ...

1623 }1622 }

1624}1623}

1625```1624```


1684 1683 

1685```json1684```json

1686{1685{

1686 "type": "error",

1687 "event_id": "event_error_123",

1688 "error": {

1687 "type": "invalid_request_error",1689 "type": "invalid_request_error",

1688 "code": "invalid_value",1690 "code": "invalid_value",

1689 "message": "Invalid value: 'scooby.dooby.doo' ...",1691 "message": "Invalid value: 'scooby.dooby.doo'.",

1690 "param": "type",1692 "param": "type",

1691 "event_id": "my_awesome_event"1693 "event_id": "my_awesome_event"

1694 }

1692}1695}

1693```1696```

1694 1697 

Details

38 38 

39Here is an example VAD configuration:39Here is an example VAD configuration:

40 40 

41```json41```jsonc

42{42{

43 "type": "session.update",43 "type": "session.update",

44 "session": {44 "session": {


51 "prefix_padding_ms": 300,51 "prefix_padding_ms": 300,

52 "silence_duration_ms": 500,52 "silence_duration_ms": 500,

53 "create_response": true, // only in conversation mode53 "create_response": true, // only in conversation mode

54 "interrupt_response": true // only in conversation mode54 "interrupt_response": true, // only in conversation mode

55 }55 },

56 }56 },

57 }57 },

58 }58 },

59}59}

60```60```

61 61 


75 75 

76It can be configured like this:76It can be configured like this:

77 77 

78```json78```jsonc

79{79{

80 "type": "session.update",80 "type": "session.update",

81 "session": {81 "session": {


84 "input": {84 "input": {

85 "turn_detection": {85 "turn_detection": {

86 "type": "semantic_vad",86 "type": "semantic_vad",

87 "eagerness": "low" | "medium" | "high" | "auto", // optional87 "eagerness": "auto", // optional

88 "create_response": true, // only in conversation mode88 "create_response": true, // only in conversation mode

89 "interrupt_response": true, // only in conversation mode89 "interrupt_response": true, // only in conversation mode

90 }90 },

91 }91 },

92 }92 },

93 }93 },

94}94}

95```95```

96 96 

Details

66 66 

67SIP carries the call audio. Use the sideband for transcripts, delegation, tools, commands, and reflected audio. Choose one owner for each side effect, even if multiple connections observe an event.67SIP carries the call audio. Use the sideband for transcripts, delegation, tools, commands, and reflected audio. Choose one owner for each side effect, even if multiple connections observe an event.

68 68 

69#### Observe keypad events

70 69 

71The sideband receives `transport.dtmf.received` when the caller presses a key and `transport.dtmf.send` after a hosted tool successfully sends a tone. Both are notifications only. The `event` field contains one of `0`–`9`, `*`, `#`, or `A`–`D`.70 

71 

72 

73#### Send and receive keypad events

74 

75The sideband receives [`transport.dtmf.received`](https://developers.openai.com/api/reference/resources/live/sideband-websocket#transport.dtmf.received) when the caller presses a key. To send a DTMF tone to the SIP trunk, send a [`transport.dtmf.send` client event](https://developers.openai.com/api/reference/resources/live/sideband-websocket#transport.dtmf.send) over the sideband WebSocket. After the tone is successfully sent, the sideband receives [`transport.dtmf.sent`](https://developers.openai.com/api/reference/resources/live/sideband-websocket#transport.dtmf.sent).

76 

77If you supply an `event_id`, the notification includes it as `client_event_id`; failures return an `error` event with `error.client_event_id`.

72 78 

73#### Transfer or end the call79#### Transfer or end the call

74 80 

Details

328 },328 },

329});329});

330 330 

331ws.on("open", function open() {331let sessionCreated = false;

332 console.log("Connected to server.");

333});

334 332 

335ws.on("message", function incoming(message) {333ws.on("message", function incoming(message) {

336 console.log(JSON.parse(message.toString()));334 const event = JSON.parse(message.toString());

335 if (event.type === "session.created") {

336 sessionCreated = true;

337 console.log("Connected to the Realtime API.", event);

338 ws.close();

339 } else if (event.type === "error") {

340 console.error(event);

341 ws.close();

342 }

343});

344ws.on("error", function handleError(error) {

345 console.error(error);

346 ws.close();

347});

348ws.on("close", function closed() {

349 if (!sessionCreated) {

350 console.error("Connection closed before the Realtime session was created.");

351 process.exitCode = 1;

352 }

337});353});

338```354```

339 355 


363]379]

364 380 

365 381 

366def on_open(ws):382session_created = False

367 print("Connected to server.")

368 383 

369 384 

370def on_message(ws, message):385def on_message(ws, message):

386 global session_created

371 data = json.loads(message)387 data = json.loads(message)

372 print("Received event:", json.dumps(data, indent=2))388 print("Received event:", json.dumps(data, indent=2))

389 if data["type"] == "session.created":

390 session_created = True

391 print("Connected to the Realtime API.")

392 ws.close()

393 elif data["type"] == "error":

394 ws.close()

373 395 

374 396 

375ws = websocket.WebSocketApp(397ws = websocket.WebSocketApp(

376 url,398 url,

377 header=headers,399 header=headers,

378 on_open=on_open,

379 on_message=on_message,400 on_message=on_message,

380)401)

381 402 

382ws.run_forever()403ws.run_forever()

404if not session_created:

405 raise RuntimeError("Connection closed before the Realtime session was created.")

383```406```

384 407 

385 408


522 "realtime",545 "realtime",

523 // Use a short-lived token fetched from your application server.546 // Use a short-lived token fetched from your application server.

524 "openai-insecure-api-key." + OPENAI_REALTIME_EPHEMERAL_KEY,547 "openai-insecure-api-key." + OPENAI_REALTIME_EPHEMERAL_KEY,

525 // Optional

526 "openai-organization." + OPENAI_ORG_ID,

527 "openai-project." + OPENAI_PROJECT_ID,

528 ]548 ]

529);549);

530 550 

Details

71| -------------------------- | :--------------------: | :------------------------: | :----------------------------: | :----------------------------: | :------------------------------------------------------: |71| -------------------------- | :--------------------: | :------------------------: | :----------------------------: | :----------------------------: | :------------------------------------------------------: |

72| `/v1/chat/completions` | No | 30 days | None, see below for exceptions | Yes, see below for limitations | Yes, see below for limitations |72| `/v1/chat/completions` | No | 30 days | None, see below for exceptions | Yes, see below for limitations | Yes, see below for limitations |

73| `/v1/responses` | No | 30 days | None, see below for exceptions | Yes, see below for limitations | Yes, see below for limitations |73| `/v1/responses` | No | 30 days | None, see below for exceptions | Yes, see below for limitations | Yes, see below for limitations |

74| `/v1/decisions` | No | 30 days | None, see below for exceptions | Yes, see below for limitations | Pending confirmation |74| `/v1/decisions` | No | 30 days | None, see below for exceptions | Yes, see below for limitations | Yes, see below for limitations |

75| `/v1/conversations` | No | Until deleted | Until deleted | No | No |75| `/v1/conversations` | No | Until deleted | Until deleted | No | No |

76| `/v1/conversations/items` | No | Until deleted | Until deleted | No | No |76| `/v1/conversations/items` | No | Until deleted | Until deleted | No | No |

77| `/v1/chatkit/threads` | No | Until deleted | Until deleted | No | No |77| `/v1/chatkit/threads` | No | Until deleted | Until deleted | No | No |


121 121 

122#### `/v1/decisions`122#### `/v1/decisions`

123 123 

124By default, abuse monitoring logs are retained for up to 30 days. Eligible customers can use Zero Data Retention, subject to the limitations below.124By default, abuse monitoring logs are retained for up to 30 days.

125 

126The Decisions API supports [Zero Data Retention](#zero-data-retention), [Private Retention with PSP](#private-retention-with-private-safety-processing), and [Safety Retention](#safety-retention), subject to the eligibility and account configuration requirements described above.

127 

128The Decisions API follows the same Private Retention with PSP policy as the Responses API. Flagged content and a sample of requests may be retained for automated safety review. See [Private Retention with PSP](#private-retention-with-private-safety-processing) for details.

129 

130The following limitations apply:

125 131 

126- Prompt caching may store encrypted key/value tensors in GPU-local storage as application state. This data is stored on the local GPU machines and is not retained after the 24-hour expiration. To learn more, see the [prompt caching guide](https://developers.openai.com/api/docs/guides/prompt-caching#prompt-cache-retention).132- Prompt caching may store encrypted key/value tensors in GPU-local storage as application state. This data is stored on the local GPU machines and is not retained after the 24-hour expiration. To learn more, see the [prompt caching guide](https://developers.openai.com/api/docs/guides/prompt-caching#prompt-cache-retention).

127- See [image and file inputs](#image-and-file-inputs) for the CSAM retention exception for image inputs.133- See [image and file inputs](#image-and-file-inputs) for the CSAM retention exception for image inputs.