Skip to main content

Overview

These hooks wrap the ChatGPT window.openai runtime APIs, providing typed React hooks for platform features that go beyond the MCP Apps standard. They are available only when running inside ChatGPT (or the simulator with the ChatGPT host selected).
These hooks throw if called outside ChatGPT. Always feature-detect with isChatGPT() before using them.

Import

import { useUploadFile, useGetFileDownloadUrl, useRequestModal, useRequestCheckout } from 'sunpeak/platform/chatgpt';
import { isChatGPT } from 'sunpeak/platform';

Feature Detection Pattern

import { isChatGPT } from 'sunpeak/platform';
import { useUploadFile } from 'sunpeak/platform/chatgpt';

function MyResource() {
  // Only use ChatGPT hooks when running on ChatGPT
  if (!isChatGPT()) {
    return <p>File upload requires ChatGPT.</p>;
  }

  return <FileUploader />;
}

function FileUploader() {
  const uploadFile = useUploadFile();
  // Safe to call — we're inside ChatGPT
  // ...
}

useUploadFile

Upload a file from the app UI into the ChatGPT conversation.

Signature

function useUploadFile(): (file: File) => Promise<CreateFileResult>

Returns

uploadFile
(file: File) => Promise<CreateFileResult>
Async function that uploads a file and returns its ID.

CreateFileResult

fileId
string
required
The ID of the uploaded file. Use with useGetFileDownloadUrl to retrieve a download URL.

Supported Formats

image/png, image/jpeg, image/webp

Usage

import { useUploadFile } from 'sunpeak/platform/chatgpt';

function ImageUploader() {
  const uploadFile = useUploadFile();

  const handleChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.currentTarget.files?.[0];
    if (!file) return;
    const { fileId } = await uploadFile(file);
    console.log('Uploaded:', fileId);
  };

  return <input type="file" accept="image/*" onChange={handleChange} />;
}

useGetFileDownloadUrl

Get a temporary download URL for a file by its ID.

Signature

function useGetFileDownloadUrl(): (params: { fileId: string }) => Promise<FileDownloadUrlResult>

Returns

getFileDownloadUrl
(params: { fileId: string }) => Promise<FileDownloadUrlResult>
Async function that retrieves a temporary download URL.

FileDownloadUrlResult

downloadUrl
string
required
Temporary URL to download the file.

Usage

import { useGetFileDownloadUrl } from 'sunpeak/platform/chatgpt';
import { useState, useEffect } from 'react';

function FilePreview({ fileId }: { fileId: string }) {
  const getFileDownloadUrl = useGetFileDownloadUrl();
  const [src, setSrc] = useState<string>();

  useEffect(() => {
    getFileDownloadUrl({ fileId }).then(({ downloadUrl }) => setSrc(downloadUrl));
  }, [fileId, getFileDownloadUrl]);

  return src ? <img src={src} /> : <p>Loading...</p>;
}

useRequestModal

Open a host-controlled modal in ChatGPT.

Signature

function useRequestModal(): (params: OpenModalParams) => Promise<void>

OpenModalParams

template
string
URL of an alternate UI template to load in the modal. Omit to reuse the current UI.
params
Record<string, unknown>
Arbitrary params forwarded to the modal content.

Usage

import { useRequestModal } from 'sunpeak/platform/chatgpt';

function SettingsButton() {
  const requestModal = useRequestModal();

  return (
    <button onClick={() => requestModal({ template: 'ui://widget/settings.html' })}>
      Open Settings
    </button>
  );
}

useRequestCheckout

Trigger the ChatGPT instant checkout flow.

Signature

function useRequestCheckout(): (session: CheckoutSession) => Promise<CheckoutOrder>

CheckoutSession

id
string
required
Unique session ID.
payment_provider
CheckoutPaymentProvider
required
Payment provider configuration.
status
'ready_for_payment'
required
Must be 'ready_for_payment' to initiate checkout.
currency
string
required
ISO 4217 currency code (e.g. 'USD').
totals
CheckoutTotal[]
required
Line items and totals.
Legal links shown during checkout.
payment_mode
'live' | 'test'
required
Whether to use live or test payment processing.

CheckoutOrder

id
string
required
Order ID.
checkout_session_id
string
required
ID of the checkout session that produced this order.
status
'completed' | string
required
Order status.
Optional permalink to the order receipt.

Usage

import { useRequestCheckout } from 'sunpeak/platform/chatgpt';

function BuyButton() {
  const requestCheckout = useRequestCheckout();

  const handleBuy = async () => {
    try {
      const order = await requestCheckout({
        id: 'session-1',
        payment_provider: {
          provider: 'stripe',
          merchant_id: 'acct_xxx',
          supported_payment_methods: ['card', 'apple_pay'],
        },
        status: 'ready_for_payment',
        currency: 'USD',
        totals: [{ type: 'total', display_text: 'Total', amount: 999 }],
        links: [],
        payment_mode: 'live',
      });
      console.log('Order completed:', order.id);
    } catch {
      console.log('Checkout cancelled or failed');
    }
  };

  return <button onClick={handleBuy}>Buy Now</button>;
}

Low-Level Access

For advanced use cases, you can access the window.openai runtime directly:
import { getOpenAIRuntime } from 'sunpeak/platform/chatgpt';
import type { OpenAIRuntime } from 'sunpeak/platform/chatgpt';

const runtime: OpenAIRuntime | undefined = getOpenAIRuntime();
if (runtime?.openExternal) {
  runtime.openExternal({ href: 'https://example.com' });
}

Simulator Support

When the ChatGPT host is selected in the Simulator, a mock window.openai runtime is automatically injected into the iframe. This makes isChatGPT() return true and all ChatGPT hooks functional with stub implementations that log to the browser console. When a different host (e.g. Claude) is selected, window.openai is not injected and isChatGPT() returns false.

See Also

Platform Detection

Detect which host platform is running your app.

Simulator

Test ChatGPT hooks locally with the mock runtime.