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.
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
The website guide documents the resulting claims:
-
profilecan include the user’s name and profile picture. -
emailcan 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
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
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
1. Generate request-bound security values
Before redirecting the user, generate:
- A random
statevalue - 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
statenoncecode_challengecode_challenge_method=S256
For identity only, request:
openid profile email
For eligible plan usage flows, request the documented additional scopes:
offline_access resource.invoke chatgpt.tokens.use.direct
Also include:
resource=https://api.openai.com/v1
3. Validate the callback
After consent, OpenAI redirects to your callback with an authorization code.
Your backend must:
- Validate the returned
state. - Exchange the authorization code at the token endpoint.
- Validate the ID token signature using OpenAI’s JWKS.
- Validate
iss,aud,exp, andnonce. - Find, create, or explicitly link the local user account.
- 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
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
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:
- Use plan usage for interactive requests from eligible Plus and Pro users.
- Use your API key for users without plan usage.
- Keep background jobs, CI, and scheduled agents on your API key.
- When the plan cap is reached, pause plan-backed requests.
- 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
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}}
This prevents secrets from being stored in saved requests or shared collections.
2. Run the Authorization Code with PKCE flow
In the Auth tab:
- Select OAuth 2.0.
- Select Authorization Code with PKCE.
- Enter the authorization and token endpoints.
- Set the scope to
openid profile email. - Use a callback URL registered for your OpenAI client.
- 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());
});
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
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
}'
In Apidog, set the request authorization to:
Bearer {{ACCESS_TOKEN}}
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)