DEV Community

Cover image for Sign in with ChatGPT for developers: the OAuth flow, plan usage, and what it means for your API bill
Hassann
Hassann

Posted on Originally published at apidog.com

Sign in with ChatGPT for developers: the OAuth flow, plan usage, and what it means for your API bill

Sign in with ChatGPT is OpenAI’s OAuth 2.0 and OpenID Connect login for ChatGPT users globally. Your app receives a stable account ID plus the user’s name, email address, and profile picture when available. Since DevDay on September 29, 2026, Plus and Pro users can also authorize participating apps to run eligible AI requests against their ChatGPT plan instead of your API key, subject to a weekly per-app cap they configure. Your app never receives their conversations, memories, or an API key.

Try Apidog today

This guide shows how to implement the flow, decide when to use plan usage versus your API key, handle failure states, and test the integration in Apidog. For the rest of the event, see the DevDay 2026 roundup. If identity and authorization are unclear, start with OAuth vs OpenID.

Sign in with ChatGPT at a glance

Item What OpenAI documents
Identity scopes openid profile email
Plan usage scopes (open-source flow) offline_access resource.invoke chatgpt.tokens.use.direct, with resource=https://api.openai.com/v1
Your app receives An ID token; with plan usage, an access token and a refresh token
Plan usage eligibility Plus and Pro, in participating apps
Where usage counts The plan’s ChatGPT Work and Codex usage
Per-app control Weekly cap as a share of overall weekly usage; credits after the cap are off by default
Plan usage tokens Access token: 1 hour; refresh token: 30 days and replaced on each refresh
Developer access Commercial apps: limited trial via an interest form. Open-source apps: self-serve

Sources: the Sign in with ChatGPT docs, token reference, and OpenAI’s help article on using your ChatGPT plan in other apps.

What your app receives—and what it does not

Start with identity-only sign-in. Request these scopes:

openid profile email
Enter fullscreen mode Exit fullscreen mode

The website guide documents the resulting claims:

  • profile can include the user’s name and profile picture.
  • email can include the email address and email-verification claims.
  • Identity scopes do not grant access to ChatGPT conversations or OpenAI API resources.

Use the verified OIDC subject as the primary account key:

issuer + client_id + sub
Enter fullscreen mode Exit fullscreen mode

Do not identify or automatically link users by email alone. OpenAI warns that a matching email address is not proof of account ownership. If an existing account has the same email, require the user to explicitly confirm the link.

Plan usage is a separate authorization grant. When a user approves the additional scopes, the token response can include:

  • An access token for eligible Responses API calls
  • A refresh token for continued access

For identity-only sign-in, do not require an access_token. The required artifact is the id_token.

Implement the OAuth flow

The website integration uses Authorization Code with PKCE plus OpenID Connect. See the Authorization Code grant with PKCE overview.

Load OpenAI endpoints from:

https://auth.openai.com/.well-known/openid-configuration
Enter fullscreen mode Exit fullscreen mode

The production values documented by OpenAI are:

Issuer:                 https://auth.openai.com
Authorization endpoint: https://auth.openai.com/api/accounts/authorize
Token endpoint:         https://auth.openai.com/api/accounts/oauth/token
JWKS URI:               https://auth.openai.com/.well-known/jwks.json
Enter fullscreen mode Exit fullscreen mode

1. Generate request-bound security values

Before redirecting the user, generate:

  • A random state value
  • A PKCE code_verifier
  • An S256 code_challenge
  • A random OIDC nonce

Store state, nonce, and the verifier server-side, associated with the pending browser session.

2. Redirect to authorization

Build an authorization request using:

  • Your client ID
  • The exact registered redirect URI
  • Your requested scopes
  • state
  • nonce
  • code_challenge
  • code_challenge_method=S256

For identity only, request:

openid profile email
Enter fullscreen mode Exit fullscreen mode

For eligible plan usage flows, request the documented additional scopes:

offline_access resource.invoke chatgpt.tokens.use.direct
Enter fullscreen mode Exit fullscreen mode

Also include:

resource=https://api.openai.com/v1
Enter fullscreen mode Exit fullscreen mode

3. Validate the callback

After consent, OpenAI redirects to your callback with an authorization code.

Your backend must:

  1. Validate the returned state.
  2. Exchange the authorization code at the token endpoint.
  3. Validate the ID token signature using OpenAI’s JWKS.
  4. Validate iss, aud, exp, and nonce.
  5. Find, create, or explicitly link the local user account.
  6. Create your own application session.

Public clients do not send a client secret. A confidential client using client_secret_basic sends its secret only through the HTTP Basic authentication header.

Open-source and locally hosted clients

Open-source tools use a different registration path. The open-source sign-in guide starts with:

client_id=dynamic_agent_client
Enter fullscreen mode Exit fullscreen mode

Include:

  • agent_name_hint: your application name
  • ext_agent_host_id: a persistent identifier for each host

The callback returns an issued client ID such as oaiapp_.... Save and reuse it. The redirect URI is a 127.0.0.1 loopback URI, and this flow does not use a client secret.

Explain plan usage to users

Your product UI and support documentation should set expectations before a user enables plan usage.

  • Eligible requests count against the user’s plan. They consume ChatGPT Work and Codex usage from a Plus or Pro subscription.
  • Each app has a weekly cap. Users configure it as a percentage of total weekly usage. The documentation’s settings example ranges from 10% to 100%.
  • The cap is not reserved capacity. Usage in ChatGPT or other connected apps can exhaust the plan before your app reaches its configured cap.
  • Credits are opt-in. Continuing on credits after limits are reached is disabled by default and requires the app cap to be set to 100%.
  • Plus has a shared five-hour limit. According to the accounts and sessions documentation, it applies across every app using the plan. It does not apply to Pro.
  • Disconnecting stops future usage. It does not reverse already consumed usage. OpenAI does not notify your application directly; detect the disconnect when a request or refresh fails.

Users manage these settings in ChatGPT under Usage:

chatgpt.com/settings/usage
Enter fullscreen mode Exit fullscreen mode

Follow OpenAI’s UI guidelines and provide a Manage usage link.

Get a client ID

OpenAI’s DevDay recap names 16 plan-usage partners, including Cognition’s Devin, Notion, Vercel, T3, OpenClaw, and Dactyl. The New Stack also lists Amp, Warp, Kilo Code, and OpenCode, with Lovable marked as coming soon. If you run OpenClaw, it appears in both lists.

As The New Stack reported, Sam Altman summarized the value on stage: “now you don’t have to cover their token costs to get them going.”

Choose the onboarding route that matches your product:

  • Commercial or hosted apps: Sign-in is a limited trial. Request a client ID through OpenAI’s interest form, whether you need identity only or plan usage.
  • Open-source and locally hosted tools: Plan usage is available to open-source partners through the self-serve flow.

Decide when to use plan usage versus your API key

Plan usage shifts eligible model costs from your API account to the user’s ChatGPT subscription. It can reduce variable model costs, but it also means your app must operate within the user’s eligibility and plan limits.

Your API key User’s ChatGPT plan
Who pays You, per token User’s plan; credits only if they opt in
Who can use it Every user Plus and Pro users who grant chatgpt.tokens.use.direct
Limits Your rate-limit tier Weekly plan usage, per-app cap, Plus five-hour window
Request shape Full Responses API store: false and stream: true required; no temperature, max_output_tokens, file search, or Code Interpreter
Typical failure 429 when you exceed your tier 429 subscription_sharing_usage_limit_exceeded, including in a mid-stream response.failed event
Fallback Your choice None automatically; OpenAI does not switch billing
What to show Your pricing and usage “Using ChatGPT plan,” a Manage usage link, and supported product plans

The preview limitations page documents the restrictions. Features requiring stored conversation state or hosted tools do not run on a user’s plan today.

A practical default is a hybrid model:

  1. Use plan usage for interactive requests from eligible Plus and Pro users.
  2. Use your API key for users without plan usage.
  3. Keep background jobs, CI, and scheduled agents on your API key.
  4. When the plan cap is reached, pause plan-backed requests.
  5. Show Manage usage and offer your own credits or billing path as a secondary option.

For broader architecture decisions, see API key vs OAuth and OAuth for AI agents.

Test the sign-in flow and failure paths in Apidog

Apidog does not sign users in with ChatGPT. Use it to exercise your OAuth configuration, token exchange requests, and application error handling.

Download Apidog and create a dedicated environment for this integration.

1. Store OAuth configuration as environment variables

Add these variables:

SIWC_CLIENT_ID
SIWC_REDIRECT_URI
SIWC_CLIENT_SECRET
ACCESS_TOKEN
Enter fullscreen mode Exit fullscreen mode

Mark SIWC_CLIENT_SECRET as sensitive for confidential clients. Reference variables in requests rather than hardcoding them:

{{SIWC_CLIENT_ID}}
{{SIWC_REDIRECT_URI}}
{{ACCESS_TOKEN}}
Enter fullscreen mode Exit fullscreen mode

This prevents secrets from being stored in saved requests or shared collections.

2. Run the Authorization Code with PKCE flow

In the Auth tab:

  1. Select OAuth 2.0.
  2. Select Authorization Code with PKCE.
  3. Enter the authorization and token endpoints.
  4. Set the scope to openid profile email.
  5. Use a callback URL registered for your OpenAI client.
  6. Complete the browser consent flow.

The Apidog OAuth 2.0 guide covers the field-by-field setup.

3. Validate the token response

Save the token exchange as its own POST request to the token endpoint. Include the authorization code, PKCE verifier, redirect URI, and client ID.

Add a post-processing script to validate the response structure:

const body = pm.response.json();

pm.test("token exchange returned an ID token", () => {
  pm.expect(pm.response.code).to.eql(200);
  pm.expect(body.id_token).to.be.a("string");
});

const decode = require("atob");
const part = body.id_token
  .split(".")[1]
  .replace(/-/g, "+")
  .replace(/_/g, "/");

const claims = JSON.parse(
  decode(part + "=".repeat((4 - (part.length % 4)) % 4))
);

pm.test("ID token claims match this client", () => {
  pm.expect(claims.iss).to.eql("https://auth.openai.com");
  pm.expect(claims.aud).to.include(pm.environment.get("SIWC_CLIENT_ID"));
  pm.expect(claims.sub).to.be.a("string").and.not.empty;
  pm.expect(claims.exp * 1000).to.be.above(Date.now());
});
Enter fullscreen mode Exit fullscreen mode

Use this only for response-level testing. Your backend must still verify the JWT signature and nonce.

Log name, email, and picture rather than asserting that they always exist, because OpenAI returns them when available.

For plan usage, also verify that the response scope contains:

chatgpt.tokens.use.direct
Enter fullscreen mode Exit fullscreen mode

4. Mock failure paths

Do not rely on a real Plus account as your only test fixture. Create Apidog mock responses for the cases your application must handle.

Scenario Mock response Expected application behavior
Plan usage declined Token response where scope does not include chatgpt.tokens.use.direct Keep the user signed in; offer plan usage setup or another billing path
Cap reached 429 with error.code set to subscription_sharing_usage_limit_exceeded Pause plan-backed requests and show Manage usage
Stream fails after starting response.failed event with subscription_sharing_usage_limit_exceeded Mark the request as failed; do not treat stream start as success
User is not eligible 403 subscription_sharing_user_not_eligible Do not retry or loop through OAuth
User disconnected Refresh returns invalid_grant, or request returns 401 subscription_sharing_invalid_user Clear stored tokens and request sign-in again

Chain these cases into a scenario and run it in CI with the Apidog CLI. OpenAI’s errors and recovery page lists the full error set.

5. Verify a live streaming request

With a real plan token, call the Responses API using the access token:

curl --no-buffer https://api.openai.com/v1/responses \
  -H "Authorization: Bearer ${ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-6.1-sol",
    "input": [{"role": "user", "content": "Say exactly: Hello, world!"}],
    "store": false,
    "stream": true
  }'
Enter fullscreen mode Exit fullscreen mode

In Apidog, set the request authorization to:

Bearer {{ACCESS_TOKEN}}
Enter fullscreen mode Exit fullscreen mode

Treat response.completed as the only success signal. A stream that starts successfully can still end with response.failed.

FAQ

Can Free users sign in with ChatGPT?

Yes. Sign in with ChatGPT is available to ChatGPT users globally. Using a ChatGPT plan inside another app requires Plus or Pro.

Does my app receive the user’s OpenAI API key?

No. Your app receives an ID token and, when plan usage is approved, an OAuth access token for eligible Responses API requests.

What happens when the user hits their cap?

Requests fail with subscription_sharing_usage_limit_exceeded. This can be an HTTP 429 or a response.failed event after streaming starts. Pause plan-backed requests and link the user to Manage usage.

Can a Plus user run GPT-6.1 Sol through a partner app?

The documentation example uses gpt-6.1-sol with a plan token. List the account’s available models with that token before offering a model in your UI. See is GPT-6.1 Sol free for more context.

Next step

If you run a commercial app, join the waitlist and implement cap-reached and disconnect handling with mocks while you wait. Treat plan usage as an optional billing path beside your own API billing, not an automatic replacement.

Save your token assertions and failure scenarios in Apidog. When your client ID arrives, the real token should be the only new variable.

Top comments (0)