# X (formerly Twitter) API, OAuth 2.0 user context: OAuth app setup guide

> Curated guide, updated 2026-10-30. Source: https://oauthseus.vercel.app/guides/x

**Difficulty:** gated. About 30 minutes to a working OAuth app; gated by prepaid pay-per-use credits and strict AI and automation policy rather than review _[documented s1,s9,s10]_

Registering an X app takes about 30 minutes with no human review. You sign in at console.x.com, accept the Developer Agreement, describe your use case, create an app, and enable OAuth 2.0 with PKCE. The hard part is price and policy, not approval. Since February 2026 the X API is pay-per-use only: there is no free read tier, every read and write is billed from prepaid credits (post read $0.005, post create $0.015, post with a URL $0.20), and the Developer Agreement forbids using X content to train foundation or frontier models.

**Your work:** 30–90 min. **Waiting on provider:** None (review depends on path).

Standard pay-per-use access needs no manual review: credentials are generated when you create the app, and access works once credits are purchased. Approval is needed only for Enterprise volume (above the 3M post-read monthly cap) or special access such as Ads API, through X sales forms. X publishes no timeline for those. X may also review or enforce against your use case at any time after the fact, because the use case description is binding.

## Launch paths

| Path | Difficulty | Your work | Provider wait |
|---|---|---|---|
| Testing / own-account prototype on pay-per-use credits | moderate | 30–60 min | None |
| Production agent for end users on pay-per-use | gated | 2–6 hours | None |
| Enterprise (high volume or special access) | gated | 2–8 hours | 2–8 weeks |

## Do these first

1. Estimate your agent's monthly reads and writes and price them with the published rates (post read $0.005, post create $0.015, post with URL $0.20) before committing
2. Sign in at console.x.com, accept the Developer Agreement, and write a precise use case description
3. Add a card, buy a small credit pack, and set a spending limit
4. Create one app, choose Type of app 'Web App, Automated App or Bot', and register exact callback URIs including http://127.0.0.1 for local dev
5. Implement PKCE with scopes tweet.read users.read offline.access (plus tweet.write if posting) and test with your own account

## What you're registering

**App in the X Developer Console (console.x.com).** One X app represents your product. Its OAuth 2.0 Client ID (and Client Secret for confidential clients) drives the Authorization Code Flow with PKCE at https://x.com/i/oauth2/authorize. Each end user who connects creates one user-context grant and token set bound to that app. All API usage by all of your users is billed to your developer account's credit balance. The Developer Policy forbids registering multiple apps for the same or overlapping use case, so do not create one app per customer. There is no dynamic client registration.

Access tokens last 2 hours. You get a refresh token only if you request the offline.access scope; without it, users must re-authorize every 2 hours. Authorization codes must be exchanged within 30 seconds. Confidential clients (Web App, Automated App or Bot) authenticate to /2/oauth2/token with HTTP Basic (client_id:client_secret). Public clients (Native App, Single Page App) send client_id in the body and use PKCE only. X keeps a single live grant per (app, user), so the same user authorizing the same app from a second client revokes the first client's tokens. OAuth 2.0 works only with API v2. Existing OAuth 1.0a user tokens can be converted with the token-exchange grant.

## What you'll need

- **X account and Developer Agreement acceptance**: Sign in at console.x.com with an X account (minimum age 13 under the X Terms) and accept the Developer Agreement and Policy. Use an account your company controls, not a personal one, because the app and billing live under it. _[documented s4]_
- **Use case description**: Describe what your app does with X data. This description is binding: substantive deviations can lead to suspension, and you must notify X and get approval before using X content for a new purpose. _[documented s10]_
- **Payment card and prepaid credits**: A credit or debit card (prepaid cards do not earn incentives). API calls are blocked when the balance is zero or negative. Configure auto-recharge (minimum $5) and a per-billing-cycle spending limit. _[documented s1]_
- **Callback URL(s) registered exactly**: Up to 10 callback URLs per app. They must match exactly, including the trailing slash, and use https in production. For local development the apps doc says to use http://127.0.0.1 rather than localhost (but see the contradiction in the verification log). _[documented s5]_
- **Website URL**: The app's authentication settings require a Website URL alongside the callback URI. Use your product's homepage. _[inferred s13]_
- **Automation Rules compliance for write actions**: Posting, following, liking or DMing on users' behalf must follow the Automation Rules. That means explicit consent before automated replies or DMs, honouring opt-outs, no bulk or aggressive actions, and no identical content across accounts. Bot accounts must disclose they are bots and who runs them. _[documented s10,s16]_
- **No model training on X content**: Clause (k) of the Developer Agreement prohibits using the X API or X Content to fine-tune or train a foundation or frontier model. An agent may read and act on content at inference time, but must not pipe it into training datasets. _[documented s9]_
- **Enterprise contract**: Required for more than 3M post reads per monthly billing cycle, or for Enterprise-only features such as team management. _[documented s1]_

## Steps

### 1. Sign in to the Developer Console and accept the Developer Agreement (5–15 min, you)

1. Go to https://console.x.com and sign in with the X account that should own the app (preferably a company account).
2. Read the Developer Agreement and Developer Policy. Pay attention to clause (k), the ban on training models on X content, and the Automation Rules.
3. Accept the Developer Agreement and Policy.
4. Complete the profile by describing how you will use the API. Be specific: say that end users connect their own accounts through OAuth 2.0 and what the agent reads and writes. This description is binding.
   - Use case description: `AI assistant that lets each user connect their own X account via OAuth 2.0 to read their timeline/mentions and draft or publish posts they approve. No X content is used for model training; no automated replies without explicit consent.` (Adapt to what your agent actually does. Deviating later can trigger enforcement.)

[Getting Access](https://docs.x.com/x-api/getting-started/getting-access) · [Developer Agreement](https://docs.x.com/developer-terms/agreement) · [Developer Policy](https://docs.x.com/developer-terms/policy) _[documented s4]_

### 2. Add a payment card, buy credits, and set a spending limit (5–15 min, you)

1. In the Developer Console open Billing and use Billing information, then Add payment method, to save a credit or debit card. Prepaid cards do not earn the incentive.
2. Buy a small amount of credits (for example $5-$10). The first purchase with your first eligible card grants a one-time $20 free credit, which expires 3 months after grant.
3. Set a Spending limit per billing cycle so a runaway agent cannot drain the balance.
4. Optionally enable auto-recharge (Recharge amount and Trigger threshold). The first successful auto-recharge is matched up to $50. Auto-recharge fires at most once per 5 minutes and is paused at zero or negative balance.
5. Check current per-endpoint rates in the console. Docs list post read $0.005, user read $0.010, post create $0.015, post create with URL $0.200, and Owned Reads $0.001 (as of 2026-10-30).

[Pricing and credits](https://docs.x.com/x-api/getting-started/pricing) · [Free credit incentives](https://docs.x.com/x-api/getting-started/free-credits) _[documented s2,s1]_

### 3. Create the app (3–10 min, you)

1. From the Developer Console dashboard click New App (some doc pages call it Create App).
2. Enter the app name, description and use case. Create one app per use case; do not create one app per customer, which violates the policy against multiple apps for one use case.
3. Credentials shown at creation (API Key and Secret, Bearer Token) are displayed only once. Copy them into a secret manager immediately.
   - App name: `<YourProduct> Agent` (Shown to users on the X consent screen.)

[Apps](https://docs.x.com/resources/fundamentals/developer-apps) · [Developer Console](https://docs.x.com/fundamentals/developer-portal) _[documented s3]_

### 4. Enable OAuth 2.0: app permissions, type of app, callback URI, website URL (5–15 min, you)

1. Open the app's settings and find the authentication settings. On the legacy portal this was 'User authentication settings', then 'Set up' (or 'Edit').
2. Set App Permissions. These apply to OAuth 1.0a; OAuth 2.0 access is governed by scopes, but choose 'Read and write' (or 'Read and write and Direct message' if you need DMs) so 1.0a tokens match.
3. Set Type of app: 'Web App, Automated App or Bot' if your agent backend can keep a secret (confidential client, gets a Client Secret). Choose 'Native App' or 'Single page App' only for public clients (PKCE only, no secret).
4. Under Callback URI / Redirect URL add each exact redirect URI (max 10), for example https://app.example.com/oauth/x/callback, plus a local dev URI.
5. Enter the Website URL (your product homepage), and optionally organization name, terms of service and privacy policy URLs.
6. Save. Then open Keys and tokens and copy the OAuth 2.0 Client ID (the long string, not the numeric app ID) and, for confidential clients, the Client Secret.
   - Type of app: `Web App, Automated App or Bot` (Confidential client. Token requests use HTTP Basic client_id:client_secret; X rejects client_secret_post per its Ads MCP doc.)
   - Callback URI / Redirect URL: `https://<your-domain>/oauth/x/callback` (Exact match including trailing slash.)
   - Callback URI / Redirect URL (local): `http://127.0.0.1:8080/callback` (The apps doc says to use 127.0.0.1, not localhost.)
   - Website URL: `https://<your-domain>`

[Apps: OAuth 2.0 app types and callback URLs](https://docs.x.com/resources/fundamentals/developer-apps) · [OAuth 2.0 Authorization Code Flow with PKCE](https://docs.x.com/resources/fundamentals/authentication/oauth-2-0/authorization-code) _[documented s5,s13]_

### 5. Implement Authorization Code Flow with PKCE and refresh (30–120 min, agent can do)

1. Build the authorize URL https://x.com/i/oauth2/authorize with response_type=code, client_id, redirect_uri, scope (space-separated), state (up to 500 chars), code_challenge and code_challenge_method=S256.
2. Request minimal scopes. A typical agent needs tweet.read users.read offline.access, plus tweet.write to post, media.write to upload media, and dm.read/dm.write only if needed.
3. Always include offline.access. Without it no refresh token is issued and users must re-consent every 2 hours.
4. On callback verify state, then POST to https://api.x.com/2/oauth2/token (Content-Type application/x-www-form-urlencoded) with code, grant_type=authorization_code, redirect_uri, and code_verifier, within 30 seconds. Confidential clients send Authorization: Basic base64(client_id:client_secret); public clients send client_id in the body.
5. Refresh with grant_type=refresh_token and store the newly returned refresh token every time.
6. Call GET https://api.x.com/2/users/me to identify the connected user (75 requests per 15 min per user).
   - scope: `tweet.read users.read offline.access` (Add tweet.write / media.write / like.write etc. only as needed.)
   - token endpoint: `https://api.x.com/2/oauth2/token`
   - authorize endpoint: `https://x.com/i/oauth2/authorize`

[OAuth 2.0 user access token guide](https://docs.x.com/resources/fundamentals/authentication/oauth-2-0/user-access-token) · [OAuth 2.0 scopes](https://docs.x.com/resources/fundamentals/authentication/oauth-2-0/authorization-code) _[documented s6,s7]_

### 6. Connect a test account end to end and watch costs (10–30 min, agent prepares, you submit)

1. Open your authorize URL, log in to X as a test user, and click Authorize app.
2. Exchange the code, call /2/users/me, then make one read and one write call.
3. Check Developer Console usage. Remember a post containing a URL costs $0.20 versus $0.015 without one, and reads are charged per returned resource, deduplicated per 24-hour UTC day.
4. Optionally poll GET /2/usage/tweets to track daily post consumption.

[Rate limits](https://docs.x.com/x-api/fundamentals/rate-limits) · [Pricing](https://docs.x.com/x-api/getting-started/pricing) _[documented s1]_

### 7. Production: compliance, bot labelling, and Enterprise if needed (1–4 hours, agent prepares, you submit)

1. Gate all automated replies, mentions and DMs behind explicit user consent, and honour opt-outs immediately.
2. If the agent operates its own bot account, label it under the account's Settings > Your account > Automation and state in the bio who runs it.
3. Handle HTTP 429 using the x-rate-limit headers. POST /2/tweets allows 100 per 15 min per user and 10,000 per 24h per app.
4. Exclude all X content from any model fine-tuning or training pipelines (Developer Agreement clause (k)).
5. If you will exceed 3M post reads per month, submit the Enterprise API interest form.

[Developer Policy: Spam, bots, and automation](https://docs.x.com/developer-terms/policy) · [Automation Rules](https://help.x.com/en/rules-and-policies/x-automation) · [Enterprise API interest form](https://docs.x.com/forms/enterprise-api-interest) _[documented s8,s10]_

## Blockers

- **API calls fail with out-of-credits / payment required** (high). Symptom: A newly created app's calls are rejected even though the credentials are valid. Fix: Buy credits in Developer Console > Billing. There is no free read allowance for new accounts. If the balance went slightly negative, add credits to cover it. Raise the auto-recharge amount if bursts drain a top-up within 5 minutes. _[documented s1]_
- **'Callback URL not approved for this client application' (code 415)** (medium). Symptom: The authorize redirect or token exchange errors immediately. Fix: Register the exact redirect_uri, including protocol, port and trailing slash, in the app's callback list, and percent-encode it in the query string. For local dev the apps doc recommends http://127.0.0.1 instead of localhost. _[documented s5]_
- **Users disconnected every 2 hours** (high). Symptom: Calls return 401 two hours after connection and there is no refresh token to use. Fix: Add offline.access to the requested scopes and have users reconnect. Persist the rotated refresh token after each refresh. _[documented s6]_
- **invalid_request on code exchange** (medium). Symptom: The token exchange fails intermittently, especially when debugging. Fix: Exchange the auth code within 30 seconds, send the same redirect_uri and the original code_verifier, and for confidential clients use an HTTP Basic header rather than client_secret in the body. _[documented s6]_
- **Tokens revoked when the same user connects through another client** (medium). Symptom: A user's earlier tokens stop working after they authorize the same app from a different client or environment. Fix: X keeps one live grant per (app, user). Use separate apps for separate clients or environments (for example dev and prod), which docs also recommend. _[documented s13]_
- **App suspended for policy violation** (high). Symptom: Email from the X platform team and the app shows as suspended. Fix: Common causes are automated replies or DMs without consent, duplicate or bulk posting, or deviating from the stated use case. Fix the behaviour and appeal through the Platform Help Form (help.x.com/forms/platform). _[documented s10]_
- **Costs explode on link posts or timeline reads** (medium). Symptom: The credit balance drains far faster than expected. Fix: A post with a URL costs $0.20 versus $0.015 without one, and reads are billed per returned resource. Cap max_results, cache (24h UTC dedup applies), use Owned Reads where possible, and set a spending limit. _[documented s1]_

## Agent vs. you

**An agent can:**
- Draft the use case description and app description text
- Generate the exact callback URIs, scope string and authorize URL
- Implement the PKCE Authorization Code Flow, token exchange (HTTP Basic for confidential clients) and refresh-token rotation
- Implement 429 handling from x-rate-limit headers and a per-user rate budget
- Estimate monthly credit spend from expected reads and writes using the published per-resource prices
- Build consent gates for automated replies and DMs and an opt-out list
- Run end-to-end API tests after a human completes the consent click

**You must:**
- Sign in to console.x.com with your X account
- Accept the Developer Agreement and Policy (legal attestation)
- Add a payment card, buy credits, and set spending limits and auto-recharge
- Click through app creation and authentication settings in the console, and copy secrets into your vault
- Authorize the app on X's consent screen as a test user
- Configure the bot account's Automation label if you run a bot account
- Negotiate any Enterprise contract

## What we couldn't confirm

- The exact current console labels for OAuth settings are uncertain. 'User authentication settings' and 'Set up' are legacy developer-portal labels, while current docs mention only App Permissions / Type of app / Callback URI / Redirect URL / Website URL / Keys and tokens. Not verified by a console walk-through.
- Whether Website URL is still mandatory in the new console is not stated in current official docs.
- Free tier: official docs list no free tier. The date it closed to new sign-ups (reported as February 6, 2026) and the treatment of legacy Basic/Pro subscribers (reported migrations around June 1 and September 1, 2026) come from community sources only.
- The Developer Agreement (Last Updated April 27, 2026) still contains monthly 'Subscription Terms' language that does not match the pay-per-use docs.
- Refresh-token lifetime and whether refresh tokens are single-use (rotating) are not documented. Community reports say they rotate; treat as unverified and always store the latest.
- Enterprise onboarding time is not published. The 2-8 week range is an unverified estimate.
- The 'Post: Create (summoned)' price ($0.010) is listed, but the qualifying conditions were not found in the pages reviewed.
- The Automation Rules page on help.x.com could not be fetched directly (bot protection). Its requirements are cited via the Developer Policy summary.
- Prices were read from docs.x.com on 2026-10-30 and X states they are subject to change. The Developer Console is the source of truth.

## Verification log

- 2026-10-30 · doc-review · **corrected**: Current access model and whether the Free/Basic/Pro tiers still exist. Commonly repeated advice (Free = write-only around 500 posts/month, Basic $200/month for reads, Pro $5,000/month) is outdated. docs.x.com/x-api/getting-started/pricing now describes only pay-per-usage credits plus Enterprise: no subscriptions, per-resource reads and per-request writes, capped at 3M post reads per monthly billing cycle. The legacy portal sign-up path (developer.x.com/en/portal/petition/essential/basic-info) still appears in older doc pages.
- 2026-10-30 · doc-review · **corrected**: Developer console location. Docs now send developers to console.x.com (the Developer Console), not developer.x.com/en/portal/dashboard. Some older doc pages still link the old portal. The pointer urlPattern covers both.
- 2026-10-30 · doc-review · **corrected**: Free credit incentive for new accounts. The $20 card-add credit is now granted only after the first credit purchase (changed October 13, 2026). Adding a card alone no longer qualifies. Incentive credits expire 3 months after grant and are spent first.
- 2026-10-30 · doc-review · **confirmed**: Access token lifetime and refresh tokens. Access tokens from the PKCE flow are valid for two hours. A refresh token is issued only with the offline.access scope. Auth codes expire after 30 seconds.
- 2026-10-30 · doc-review · **corrected**: Localhost vs 127.0.0.1 for local callback URLs. The Apps doc says local development should use http://127.0.0.1, not localhost. However, X's own MCP docs register http://localhost:8080/callback for the xurl bridge and Claude Code. The docs contradict each other; 127.0.0.1 is the safer documented choice.
- 2026-10-30 · doc-review · **confirmed**: AI/model-training restriction in Developer Agreement. Developer Agreement (Last Updated April 27, 2026), Section restrictions clause (k), forbids using the X API or X Content to fine-tune or train a foundation or frontier model.
- 2026-10-30 · doc-review · **confirmed**: One live grant per (app, user). The X Ads MCP doc states that signing in from a second client revokes the first client's tokens for the same app and user. This is rarely mentioned in OAuth guides and matters for agents with multiple clients.
- 2026-10-30 · doc-review · **confirmed**: Dynamic client registration for MCP-style agents. The X MCP doc says there is no dynamic client registration. You must create your own developer app and register its callback.
- 2026-10-30 · doc-review · **confirmed**: Rate limits for key endpoints. POST /2/tweets: 10,000/24h per app, 100/15min per user. GET /2/users/me: 75/15min per user. GET /2/tweets/search/recent: 450/15min per app, 300/15min per user.
- 2026-10-30 · http-probe · **confirmed**: Automated: developer console (https://console.x.com/). Loaded: "Developer Console".
- 2026-10-30 · http-probe · **confirmed**: Automated: authorize endpoint with a fake client_id (https://x.com/i/oauth2/authorize). Endpoint answered HTTP 200 ("Authorize app / X").
- 2026-10-30 · doc-review · **confirmed**: Automated: 27 quotes re-fetched and matched against their cited pages. 27 of 27 quotes found verbatim in the live page HTML.  15/16 source URLs returned HTTP 200.

## Sources

- s1: [X API pay-per-usage pricing and credits](https://docs.x.com/x-api/getting-started/pricing) (official-docs, accessed 2026-10-30)
- s2: [Free credit incentives for X API pay-per-use accounts](https://docs.x.com/x-api/getting-started/free-credits) (official-docs, accessed 2026-10-30)
- s3: [Developer Console](https://docs.x.com/fundamentals/developer-portal) (official-docs, accessed 2026-10-30)
- s4: [Getting Access](https://docs.x.com/x-api/getting-started/getting-access) (official-docs, accessed 2026-10-30)
- s5: [Apps](https://docs.x.com/resources/fundamentals/developer-apps) (official-docs, accessed 2026-10-30)
- s6: [OAuth 2.0 Authorization Code Flow with PKCE (reference)](https://docs.x.com/resources/fundamentals/authentication/oauth-2-0/authorization-code) (official-docs, accessed 2026-10-30)
- s7: [OAuth 2.0 Authorization Code Flow with PKCE (how to connect)](https://docs.x.com/resources/fundamentals/authentication/oauth-2-0/user-access-token) (official-docs, accessed 2026-10-30)
- s8: [Rate limits](https://docs.x.com/x-api/fundamentals/rate-limits) (official-docs, accessed 2026-10-30)
- s9: [X Developer Agreement](https://docs.x.com/developer-terms/agreement) (official-policy, accessed 2026-10-30)
- s10: [X Developer Policy](https://docs.x.com/developer-terms/policy) (official-policy, accessed 2026-10-30)
- s11: [Restricted uses of the X API](https://docs.x.com/developer-terms/more-on-restricted-use-cases) (official-policy, accessed 2026-10-30)
- s12: [MCP servers (X MCP and Docs MCP)](https://docs.x.com/tools/mcp) (official-docs, accessed 2026-10-30)
- s13: [X Ads MCP](https://docs.x.com/x-ads-api/mcp) (official-docs, accessed 2026-10-30)
- s14: [X shifts API to Pay-Per-Use; free plan effectively discontinued (roboin)](https://roboin.io/article/en/2026/02/08/x-transitions-api-to-pay-per-use-model-ending-free-plan/) (community, accessed 2026-10-30)
- s15: [X is moving legacy Basic API plans to pay-per-use (maxrave.dev)](https://maxrave.dev/articles/x-legacy-basic-api-plans-moving-to-pay-per-use) (community, accessed 2026-10-30)
- s16: [X Automation Rules](https://help.x.com/en/rules-and-policies/x-automation) (official-policy, accessed 2026-10-30)
- p1: [Live probe (console): Loaded: "Developer Console".](https://console.x.com/) (probe, accessed 2026-10-30)
- p2: [Live probe (authorize-endpoint): Endpoint answered HTTP 200 ("Authorize app / X").](https://x.com/i/oauth2/authorize) (probe, accessed 2026-10-30)

Evidence tags: tested = exercised live; documented = official source, quote checked; inferred = reasoning; unverified = unconfirmed.