# X Emulator (service host) Create an instance: curl -s -X POST https://x.emulators.dev/_emulate/instances # Hosted deployments create instances lazily when the returned URL is first used. The instance URL is a capability: anyone who has it can read and modify the instance, so save the returned URLs. Never store real secrets in an emulator. # The server generates an unguessable name. An optional {"instance":""} body adds a readable prefix. Then use the returned providerBaseUrl / controlBaseUrl. Example below uses a sample instance. # X Emulator Stateful X (formerly Twitter) API v2 emulator focused on faithful auth: app-only Bearer tokens, OAuth 2.0 Authorization Code with PKCE, and a documented-partial legacy OAuth 1.0a surface. Provider base URL: https://x.your-instance.emulators.dev Control base URL: https://x.your-instance.emulators.dev/_emulate Supported surfaces: - X API v2 (REST): partial at /2 - OAuth 2.0 Authorization Code (PKCE): supported at /2/oauth2 - App-only Bearer token (client credentials): supported at /2/oauth2/token - Legacy OAuth 1.0a user context: unsupported Control endpoints: - https://x.your-instance.emulators.dev/_emulate/manifest - https://x.your-instance.emulators.dev/_emulate/coverage - https://x.your-instance.emulators.dev/_emulate/connections - https://x.your-instance.emulators.dev/_emulate/state - https://x.your-instance.emulators.dev/_emulate/ledger - https://x.your-instance.emulators.dev/_emulate/faults - POST https://x.your-instance.emulators.dev/_emulate/credentials - POST https://x.your-instance.emulators.dev/_emulate/seed - POST https://x.your-instance.emulators.dev/_emulate/reset Fault injection: Arm a one-shot provider failure with a glob pathPattern, then inspect /ledger for faulted: true. curl -s -X POST https://x.your-instance.emulators.dev/_emulate/faults \ -H "content-type: application/json" \ -d '{"match":{"method":"GET","pathPattern":"/v1/*"},"response":{"status":503,"body":{"error":"temporary"}}}' Connect: ## twitter-api-v2 (TypeScript) import { TwitterApi } from "twitter-api-v2"; const base = "https://x.your-instance.emulators.dev"; // App-only Bearer token (client_credentials). const appClient = new TwitterApi("", { baseUrl: base }); const user = await appClient.v2.userByUsername("developer"); // OAuth 2.0 user-context client (Authorization Code with PKCE). const oauthClient = new TwitterApi({ clientId: "", clientSecret: "" }); const { url, codeVerifier, state } = oauthClient.generateOAuth2AuthLink( "http://localhost:3000/api/auth/callback/twitter", { scope: ["tweet.read", "tweet.write", "users.read", "offline.access"] }, ); // Send the user to `url` (against `${base}/2/oauth2/authorize`), then exchange the code at `${base}/2/oauth2/token`. ## X base URL and credentials (env) X_API_BASE_URL=https://x.your-instance.emulators.dev X_CLIENT_ID= X_CLIENT_SECRET= X_BEARER_TOKEN= ## curl (app-only Bearer) curl -s -X POST https://x.your-instance.emulators.dev/2/oauth2/token \ -u ":" \ -d grant_type=client_credentials curl -s https://x.your-instance.emulators.dev/2/users/by/username/developer \ -H "authorization: Bearer " ## curl (authorization code + PKCE) curl -s -X POST https://x.your-instance.emulators.dev/2/oauth2/token \ -u ":" \ -d grant_type=authorization_code \ -d code=$CODE \ -d redirect_uri=http://localhost:3000/api/auth/callback/twitter \ -d code_verifier=$CODE_VERIFIER ## Base URL (env) X_BASE_URL=https://x.your-instance.emulators.dev ## Create a credential curl -s -X POST https://x.your-instance.emulators.dev/_emulate/credentials \ -H "content-type: application/json" \ -d '{"type":"bearer-token"}' ## Inspect requests curl -s https://x.your-instance.emulators.dev/_emulate/ledger