{"version":"2","product":{"name":"Payphone","tagline":"SMS updates from coding agents","bootstrapPromptTitle":"Payphone Agent Bootstrap"},"baseUrl":"https://payphone.wtf","authModes":["apikey","privy","x402"],"recommendedForAgents":"apikey","onboardingScopes":["account:read","sms:send","numbers:read","numbers:buy"],"scopes":["account:read","sms:send","numbers:buy","numbers:read","lookup:read","dehashed:search","esim:order","verifications:start"],"baseRoutes":["GET /api/v1/account","GET /api/v1/account/credits"],"scopeRoutes":{"account:read":["GET /api/v1/account/usage","GET /api/v1/account/history","GET /api/v1/account/subscription"],"sms:send":["POST /api/v1/sms/send","POST /api/v1/messaging/send","POST /api/v1/numbers/mine/send"],"numbers:buy":["POST /api/v1/numbers/buy","POST /api/v1/numbers/buy/us","POST /api/v1/numbers/buy/intl","POST /api/v1/xmpp/provision","POST /api/v1/numbers/mine/renew"],"numbers:read":["GET /api/v1/numbers/mine","GET /api/v1/numbers/mine/messages","GET /api/v1/numbers/buy/status","GET /api/v1/sms/inbox","PUT /api/v1/numbers/mine/webhook","GET /api/v1/messaging/threads","GET /api/v1/messaging/threads/:counterparty"],"lookup:read":["POST /api/v1/lookup"],"dehashed:search":["POST /api/v1/dehashed/search","POST /api/v1/dehashed/search-with-credits"],"esim:order":["POST /api/v1/esim/checkout"],"verifications:start":["POST /api/v1/verifications/start"]},"bootstrapSteps":[{"step":1,"action":"fetch_manifest","description":"Fetch https://payphone.wtf/.well-known/dial-onboarding.json — treat it as the single source of truth for installers, env, MCP, skills, and verification.","path":"https://payphone.wtf/.well-known/dial-onboarding.json"},{"step":2,"action":"detect_environment","description":"Detect agent runtime using manifest.installers (Cursor, Claude Code, Codex, OpenCode, VS Code). Pick the matching live installer; if none match, use REST + skill URLs from the manifest."},{"step":3,"action":"install_adapter","description":"Cursor: run pnpm cursor:agent:setup -- --api-key <key> --phone <E.164> from a Payphone repo clone (plugin + rules + skills + env + test SMS). Add --with-project-mcp only if you also want project Installed MCP. Fallback: pnpm cursor:plugin:install. Idempotent."},{"step":4,"action":"configure_env","description":"Store DIAL_API_URL, DIAL_API_KEY, DIAL_NOTIFY_PHONE. Set DIAL_OWNED_LINE_E164 only when sending from a leased number; otherwise agents use pool send. Never commit keys."},{"step":5,"action":"verify_api_key","description":"GET https://payphone.wtf/api/v1/account with Authorization: Bearer <key>.","method":"GET","path":"https://payphone.wtf/api/v1/account"},{"step":6,"action":"validate_owned_line","description":"When DIAL_OWNED_LINE_E164 is set: GET https://payphone.wtf/api/v1/numbers/mine and confirm the line is active (not suspended/orphaned/expired) before sending.","method":"GET","path":"https://payphone.wtf/api/v1/numbers/mine"},{"step":7,"action":"register_mcp","description":"Cursor: Settings → MCP → Plugin MCP Servers → dial → Login. Fallback: write project .cursor/mcp.json pointing at manifest cursorPlugin.mcpUrl."},{"step":8,"action":"install_behavior_pack","description":"Ensure operator SMS rule + dial/payphone skills are active (included in Cursor plugin; for other agents copy skill URL from manifest when tranche 2 ships)."},{"step":9,"action":"confirm_preferences","description":"Ask which events the operator wants (started, progress, blocked, approval, failed, completed). Write .payphone/operator-notifications.json from the template; user can edit later."},{"step":10,"action":"confirm_phone","description":"Use operator phone from user context as DIAL_NOTIFY_PHONE, or ask once for E.164. Do not send SMS before the number is confirmed."},{"step":11,"action":"send_test_operator_update","description":"Pool (default): POST https://payphone.wtf/api/v1/sms/send with \"Payphone pool test — confirm in Cursor chat (pool cannot receive SMS replies).\" — confirm in Cursor chat, not SMS reply. Owned line: POST numbers/mine/send with \"Payphone setup: reply Y if you got this, N if not.\" — poll inbox for Y/Yes.","method":"POST","path":"https://payphone.wtf/api/v1/sms/send"},{"step":12,"action":"report","description":"Report: detected agent, send path (pool vs owned), env locations, MCP status, test messageId, delivery confirmation method. Do not paste the full API key."}],"selfSetupSteps":[{"step":1,"description":"Read https://payphone.wtf/skill.md and follow Payphone conventions.","path":"https://payphone.wtf/skill.md"},{"step":2,"description":"Verify the API key: GET https://payphone.wtf/api/v1/account with Authorization: Bearer <key>.","method":"GET","path":"https://payphone.wtf/api/v1/account"},{"step":3,"description":"Default pool test: POST https://payphone.wtf/api/v1/sms/send with \"Payphone pool test — confirm in Cursor chat (pool cannot receive SMS replies).\" (outbound-only — no SMS replies).","method":"POST","path":"https://payphone.wtf/api/v1/sms/send"},{"step":4,"description":"Verify account routes: GET /api/v1/account and GET /api/v1/account/credits.","method":"GET","path":"https://payphone.wtf/api/v1/account/credits"},{"step":5,"description":"Two-way SMS: POST https://payphone.wtf/api/v1/numbers/buy/us (or intl), poll buy/status, set DIAL_OWNED_LINE_E164, send via POST https://payphone.wtf/api/v1/numbers/mine/send.","method":"POST","path":"https://payphone.wtf/api/v1/numbers/buy/us"},{"step":6,"description":"Poll provisioning: GET https://payphone.wtf/api/v1/numbers/buy/status?jobId=... (numbers:read).","method":"GET","path":"https://payphone.wtf/api/v1/numbers/buy/status"},{"step":7,"description":"Confirm delivery. Pool: messages.status or account/history. Owned line: GET https://payphone.wtf/api/v1/sms/inbox or messaging threads — replies only on leased lines.","method":"GET","path":"https://payphone.wtf/api/v1/sms/inbox"}],"activationFlow":["installation_started","client_detected","integration_registered","credentials_stored","api_verified","phone_confirmed","test_sms_sent","active"],"requiredEnv":["DIAL_API_URL","DIAL_API_KEY","DIAL_NOTIFY_PHONE"],"optionalEnv":[{"name":"DIAL_OWNED_LINE_E164","description":"When set, agent sends use POST /api/v1/numbers/mine/send from this leased E.164 only. When unset, agents use pool send (POST /api/v1/sms/send) — shared outbound-only, not an owned line.","example":"DIAL_OWNED_LINE_E164=+19142285559"}],"installers":{"cursor":{"status":"live","detectHints":["cursor","Composer","Plugin MCP Servers"],"method":"cursor-plugin-copy","installCommand":"pnpm cursor:agent:setup","pluginOnlyCommand":"pnpm cursor:plugin:install","validateCommand":"pnpm cursor:plugin:validate","pluginPath":"packages/cursor-plugin","mcpRegistration":"plugin-mcp-json","envTargets":["cursor-settings-environment","shell-profile","cloud-agent-secrets"]},"claude-code":{"status":"planned","detectHints":["Claude Code",".claude/skills"],"method":"skill-plugin","installCommand":"npx @payphone/setup claude-code","skillPackage":"packages/skill"},"codex":{"status":"planned","detectHints":["Codex","AGENTS.md"],"method":"setup-cli","installCommand":"npx @payphone/setup codex"},"opencode":{"status":"planned","detectHints":["OpenCode","opencode"],"method":"setup-cli","installCommand":"npx @payphone/setup opencode"},"vscode":{"status":"planned","detectHints":["VS Code","GitHub Copilot"],"method":"mcp-json","mcpUrlKey":"mcpServers.dial.url"}},"distributionChannels":{"payphoneBootstrap":{"status":"live","primaryAction":"copy_automatic_setup","sourceParam":"payphone_bootstrap"},"cursorMarketplace":{"status":"planned","primaryAction":"install","sourceParam":"cursor_marketplace"},"github":{"status":"live","primaryAction":"choose_install_path","sourceParam":"github"},"cursorDirectory":{"status":"planned","primaryAction":"add_mcp_to_cursor","sourceParam":"cursor_directory"},"teamMarketplace":{"status":"planned","primaryAction":"admin_provision","sourceParam":"team_marketplace"}},"cursorPlugin":{"installCommand":"pnpm cursor:agent:setup","validateCommand":"pnpm cursor:plugin:validate","mcpUrl":"https://payphone.wtf/mcp","setupCommand":"/dial-setup","notifyCommand":"/dial-notify","skill":"operator-sms","rule":"dial-agent"},"operatorNotifications":{"mcpTool":"send_operator_update","restFallbackScript":"packages/cursor-plugin/scripts/operator-notify.sh","policyFile":".payphone/operator-notifications.json","policyFields":{"ownedLineE164":{"description":"Your leased E.164 for outbound SMS. Omit or null = pool send (shared numbers, outbound-only). Validate with GET /api/v1/numbers/mine.","default":null},"phoneE164":{"description":"Operator recipient for milestone texts (mirrors DIAL_NOTIFY_PHONE).","default":null}},"policyTemplate":"packages/cursor-plugin/templates/operator-notifications.json","policyInstallScript":"packages/cursor-plugin/scripts/install-operator-policy.sh","defaultEvents":{"started":true,"progress":true,"blocked":true,"approval_required":true,"failed":true,"completed":true},"statusValues":["started","progress","blocked","approval_required","failed","completed"],"sendWhen":["substantial_work_started","meaningful_milestone","blocked_on_operator","approval_required","progress_stopped","work_completed"],"doNotSendWhen":["routine_file_edits","every_terminal_command","minor_self_fixable_errors","duplicate_updates","secrets_or_tokens"]},"verification":{"testTool":"send_operator_update","testStatus":"started","testSummary":"Payphone operator SMS is configured."},"endpoints":{"account":{"method":"GET","path":"/api/v1/account"},"accountCredits":{"method":"GET","path":"/api/v1/account/credits"},"accountHistory":{"method":"GET","path":"/api/v1/account/history","primaryScope":"account:read"},"smsSendPool":{"method":"POST","path":"/api/v1/sms/send","price":"$0.05","creditsPerCall":1,"primaryScope":"sms:send"},"smsSendOwn":{"method":"POST","path":"/api/v1/numbers/mine/send","price":"$0.05","creditsPerCall":1,"primaryScope":"sms:send"},"numbersBuyUs":{"method":"POST","path":"/api/v1/numbers/buy/us","price":"$100.00","primaryScope":"numbers:buy"},"numbersBuyIntl":{"method":"POST","path":"/api/v1/numbers/buy/intl","price":"$100.00","primaryScope":"numbers:buy"},"numbersBuyStatus":{"method":"GET","path":"/api/v1/numbers/buy/status","primaryScope":"numbers:read"},"smsInbox":{"method":"GET","path":"/api/v1/sms/inbox","primaryScope":"numbers:read"}},"docs":{"apiKeys":"https://payphone.wtf/docs/api-reference/api-keys","humanQuickstart":"https://payphone.wtf/docs/onboarding/quickstart","agentQuickstart":"https://payphone.wtf/docs/onboarding/agent-quickstart","agentNativeRoadmap":"https://payphone.wtf/specs/agent-native-onboarding-roadmap.md","llmsFull":"https://payphone.wtf/llms-full.txt","skill":"https://payphone.wtf/skill.md","mcp":"https://payphone.wtf/mcp","manifest":"https://payphone.wtf/.well-known/dial-onboarding.json"},"deliveryNote":"POST /api/v1/sms/send (pool) returning 200 means queued, not Cheogram-delivered. Pool numbers are outbound-only — recipients cannot reply by SMS. For two-way SMS, buy a dedicated line and send via POST /api/v1/numbers/mine/send; confirm via GET /api/v1/sms/inbox.","smsSendModes":{"pool":{"id":"pool","endpoint":"/api/v1/sms/send","inbound":false,"replySupported":false,"agentDefault":true,"note":"Default for operator notifications and quick tests. Recipients cannot reply; inbound SMS is not supported on pool numbers."},"dedicated":{"id":"dedicated","buyEndpoint":"/api/v1/numbers/buy/us","sendEndpoint":"/api/v1/numbers/mine/send","inboxEndpoint":"/api/v1/sms/inbox","inbound":true,"replySupported":true,"note":"Buy with numbers:buy, send from your E.164 via numbers/mine/send. Required when the user must reply by SMS."}}}